Repository: James231/Start-Menu-Manager Branch: master Commit: 577e5ce171b4 Files: 154 Total size: 755.0 KB Directory structure: gitextract_gz0lcu5f/ ├── .gitignore ├── CustomAnalysisRules.Test.ruleset ├── CustomAnalysisRules.ruleset ├── Directory.Build.props ├── LICENSE ├── README.md ├── StartMenuManager.sln ├── src/ │ ├── HL/ │ │ ├── AssemblyInfo.cs │ │ ├── HL.csproj │ │ ├── HighlightingTheme/ │ │ │ ├── GlobalStyle.cs │ │ │ └── SyntaxDefinition.cs │ │ ├── Interfaces/ │ │ │ ├── IHLTheme.cs │ │ │ └── IThemedHighlightingManager.cs │ │ ├── LICENSE │ │ ├── Manager/ │ │ │ ├── BusyManager.cs │ │ │ ├── DefaultHighlightingManager.cs │ │ │ ├── DelayLoadedHighlightingDefinition.cs │ │ │ ├── ExtensionMethods.cs │ │ │ ├── HLTheme.cs │ │ │ ├── HighlightingBrush.cs │ │ │ ├── HighlightingLoader.cs │ │ │ ├── HighlightingThemeLoader.cs │ │ │ ├── ThemedHighlightingManager.cs │ │ │ ├── V2Loader.cs │ │ │ ├── XmlHighlightingDefinition.cs │ │ │ └── XshtdLoader.cs │ │ ├── Modes/ │ │ │ ├── ModeV1.xsd │ │ │ ├── ModeV2.xsd │ │ │ └── ModeV2_htd.xsd │ │ ├── Resources/ │ │ │ ├── HLResources.cs │ │ │ ├── Light/ │ │ │ │ ├── AS3.xshd │ │ │ │ ├── ASPX.xshd │ │ │ │ ├── Boo.xshd │ │ │ │ ├── CPP-Mode.xshd │ │ │ │ ├── CSS-Mode.xshd │ │ │ │ ├── CSharp-Mode.xshd │ │ │ │ ├── Coco-Mode.xshd │ │ │ │ ├── DOSBATCH.xshd │ │ │ │ ├── FSharp-Mode.xshd │ │ │ │ ├── GRazor-Mode.xshd │ │ │ │ ├── Gcode.xshd │ │ │ │ ├── HLSL.xshd │ │ │ │ ├── HTML-Mode.xshd │ │ │ │ ├── INI.xshd │ │ │ │ ├── Java-Mode.xshd │ │ │ │ ├── JavaScript-Mode.xshd │ │ │ │ ├── Log.xshd │ │ │ │ ├── MarkDown-Mode.xshd │ │ │ │ ├── PHP-Mode.xshd │ │ │ │ ├── PLSQL.xshd │ │ │ │ ├── Pascal.xshd │ │ │ │ ├── Patch-Mode.xshd │ │ │ │ ├── PowerShell.xshd │ │ │ │ ├── Python-Mode.xshd │ │ │ │ ├── Ruby.xshd │ │ │ │ ├── TSQL-Mode.xshd │ │ │ │ ├── TXT.xshd │ │ │ │ ├── Tex-Mode.xshd │ │ │ │ ├── VB-Mode.xshd │ │ │ │ ├── XML-Mode.xshd │ │ │ │ ├── XmlDoc.xshd │ │ │ │ ├── scheme.xshd │ │ │ │ ├── squirrel.xshd │ │ │ │ └── vtl.xshd │ │ │ └── Themes/ │ │ │ ├── Dark.xshtd │ │ │ ├── TrueBlue.xshtd │ │ │ └── VS2019_Dark.xshtd │ │ └── Xshtd/ │ │ ├── IXshtdVisitor.cs │ │ ├── XhstdThemeDefinition.cs │ │ ├── XmlHighlightingThemeDefinition.cs │ │ ├── XshtdColor.cs │ │ ├── XshtdElement.cs │ │ ├── XshtdGlobalStyle.cs │ │ ├── XshtdGlobalStyles.cs │ │ ├── XshtdSyntaxDefinition.cs │ │ └── interfaces/ │ │ ├── IFreezable.cs │ │ ├── IHighlightingDefinitionReferenceResolver.cs │ │ └── IHighlightingThemeDefinition.cs │ ├── StartMenuManager.Builder/ │ │ ├── App.config │ │ ├── Program.cs │ │ ├── Properties/ │ │ │ └── AssemblyInfo.cs │ │ └── StartMenuManager.Builder.csproj │ ├── StartMenuManager.Core/ │ │ ├── DataStructures/ │ │ │ ├── Action.cs │ │ │ ├── Actions/ │ │ │ │ ├── CommandAction.cs │ │ │ │ ├── FileAction.cs │ │ │ │ ├── FolderAction.cs │ │ │ │ ├── SoftwareAction.cs │ │ │ │ └── WebsiteAction.cs │ │ │ ├── Config.cs │ │ │ ├── SettingsConfig.cs │ │ │ ├── Shortcut.cs │ │ │ └── ValidationError.cs │ │ ├── Serialization/ │ │ │ └── Serializer.cs │ │ └── StartMenuManager.Core.csproj │ ├── StartMenuManager.GUI/ │ │ ├── App.config │ │ ├── App.xaml │ │ ├── App.xaml.cs │ │ ├── Builder.cs │ │ ├── Dialogs/ │ │ │ ├── MessageDialog.cs │ │ │ ├── SettingsDialog.cs │ │ │ └── YesNoDialog.cs │ │ ├── Extensions/ │ │ │ └── ActionExtensions.cs │ │ ├── IconExtractorWindow.xaml │ │ ├── IconExtractorWindow.xaml.cs │ │ ├── JsonViewManager.cs │ │ ├── LowerMenuBar.cs │ │ ├── MainWindow.xaml │ │ ├── MainWindow.xaml.cs │ │ ├── Properties/ │ │ │ ├── AssemblyInfo.cs │ │ │ ├── Resources.Designer.cs │ │ │ ├── Resources.resx │ │ │ ├── Settings.Designer.cs │ │ │ └── Settings.settings │ │ ├── Runner.cs │ │ ├── Serialization/ │ │ │ ├── IconManager.cs │ │ │ └── JsonSerializer.cs │ │ ├── ShortcutControl.xaml │ │ ├── ShortcutControl.xaml.cs │ │ ├── ShortcutListArea.cs │ │ ├── StartMenuManager.GUI.csproj │ │ ├── Structures/ │ │ │ ├── DialogTypes.cs │ │ │ └── ShortcutType.cs │ │ ├── SubShortcutControl.xaml │ │ ├── SubShortcutControl.xaml.cs │ │ ├── TitleBarButtons.cs │ │ ├── Utils/ │ │ │ ├── DialogManager.cs │ │ │ ├── IconExtractorWindow_TitleBarControl.cs │ │ │ ├── ThemeManager.cs │ │ │ ├── TitleBarControl.cs │ │ │ └── WindowRef.cs │ │ ├── WelcomeCard.cs │ │ └── app.manifest │ ├── StartMenuManager.GUI.Installer/ │ │ ├── Product.wxs │ │ ├── StartMenuManager.GUI.Installer.wixproj │ │ └── netchecker.wxs │ ├── StartMenuManager.PreUninstall/ │ │ ├── App.config │ │ ├── Program.cs │ │ ├── Properties/ │ │ │ └── AssemblyInfo.cs │ │ └── StartMenuManager.PreUninstall.csproj │ ├── StartMenuManager.Runner/ │ │ ├── App.config │ │ ├── Program.cs │ │ ├── Properties/ │ │ │ └── AssemblyInfo.cs │ │ └── StartMenuManager.Runner.csproj │ └── TextEditLib/ │ ├── AssemblyInfo.cs │ ├── Extensions/ │ │ └── HighlightCurrentLineBackgroundRenderer.cs │ ├── TextEdit.xaml │ ├── TextEdit.xaml.cs │ ├── TextEditLib.csproj │ └── Themes/ │ ├── DarkBrushs.xaml │ ├── Generic.xaml │ ├── Icons.xaml │ ├── LightBrushs.xaml │ └── ResourceKeys.cs └── stylecop.json ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ ## Ignore Visual Studio temporary files, build results, and ## files generated by popular Visual Studio add-ons. ## ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore # User-specific files *.suo *.user *.userosscache *.sln.docstates # User-specific files (MonoDevelop/Xamarin Studio) *.userprefs # Build results [Dd]ebug/ [Dd]ebugPublic/ [Rr]elease/ [Rr]eleases/ x64/ x86/ bld/ [Bb]in/ [Oo]bj/ [Ll]og/ # Visual Studio 2015/2017 cache/options directory .vs/ # Uncomment if you have tasks that create the project's static files in wwwroot #wwwroot/ # Visual Studio 2017 auto generated files Generated\ Files/ # MSTest test Results [Tt]est[Rr]esult*/ [Bb]uild[Ll]og.* # NUNIT *.VisualState.xml TestResult.xml # Build Results of an ATL Project [Dd]ebugPS/ [Rr]eleasePS/ dlldata.c # Benchmark Results BenchmarkDotNet.Artifacts/ # .NET Core project.lock.json project.fragment.lock.json artifacts/ **/Properties/launchSettings.json # StyleCop StyleCopReport.xml # Files built by Visual Studio *_i.c *_p.c *_i.h *.ilk *.meta *.obj *.iobj *.pch *.pdb *.ipdb *.pgc *.pgd *.rsp *.sbr *.tlb *.tli *.tlh *.tmp *.tmp_proj *.log *.vspscc *.vssscc .builds *.pidb *.svclog *.scc # Chutzpah Test files _Chutzpah* # Visual C++ cache files ipch/ *.aps *.ncb *.opendb *.opensdf *.sdf *.cachefile *.VC.db *.VC.VC.opendb # Visual Studio profiler *.psess *.vsp *.vspx *.sap # TFS 2012 Local Workspace $tf/ # Guidance Automation Toolkit *.gpState # ReSharper is a .NET coding add-in _ReSharper*/ *.[Rr]e[Ss]harper *.DotSettings.user # JustCode is a .NET coding add-in .JustCode # TeamCity is a build add-in _TeamCity* # DotCover is a Code Coverage Tool *.dotCover # AxoCover is a Code Coverage Tool .axoCover/* !.axoCover/settings.json # Visual Studio code coverage results *.coverage *.coveragexml # NCrunch _NCrunch_* .*crunch*.local.xml nCrunchTemp_* # MightyMoose *.mm.* AutoTest.Net/ # Web workbench (sass) .sass-cache/ # Installshield output folder [Ee]xpress/ # DocProject is a documentation generator add-in DocProject/buildhelp/ DocProject/Help/*.HxT DocProject/Help/*.HxC DocProject/Help/*.hhc DocProject/Help/*.hhk DocProject/Help/*.hhp DocProject/Help/Html2 DocProject/Help/html # Click-Once directory publish/ # Publish Web Output *.[Pp]ublish.xml *.azurePubxml # Note: Comment the next line if you want to checkin your web deploy settings, # but database connection strings (with potential passwords) will be unencrypted *.pubxml *.publishproj # Microsoft Azure Web App publish settings. Comment the next line if you want to # checkin your Azure Web App publish settings, but sensitive information contained # in these scripts will be unencrypted PublishScripts/ # NuGet Packages *.nupkg # The packages folder can be ignored because of Package Restore **/[Pp]ackages/* # except build/, which is used as an MSBuild target. !**/[Pp]ackages/build/ # Uncomment if necessary however generally it will be regenerated when needed #!**/[Pp]ackages/repositories.config # NuGet v3's project.json files produces more ignorable files *.nuget.props *.nuget.targets # Microsoft Azure Build Output csx/ *.build.csdef # Microsoft Azure Emulator ecf/ rcf/ # Windows Store app package directories and files AppPackages/ BundleArtifacts/ Package.StoreAssociation.xml _pkginfo.txt *.appx # Visual Studio cache files # files ending in .cache can be ignored *.[Cc]ache # but keep track of directories ending in .cache !*.[Cc]ache/ # Others ClientBin/ ~$* *~ *.dbmdl *.dbproj.schemaview *.jfm *.pfx *.publishsettings orleans.codegen.cs # Including strong name files can present a security risk # (https://github.com/github/gitignore/pull/2483#issue-259490424) #*.snk # Since there are multiple workflows, uncomment next line to ignore bower_components # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) #bower_components/ # RIA/Silverlight projects Generated_Code/ # Backup & report files from converting an old project file # to a newer Visual Studio version. Backup files are not needed, # because we have git ;-) _UpgradeReport_Files/ Backup*/ UpgradeLog*.XML UpgradeLog*.htm ServiceFabricBackup/ *.rptproj.bak # SQL Server files *.mdf *.ldf *.ndf # Business Intelligence projects *.rdl.data *.bim.layout *.bim_*.settings *.rptproj.rsuser # Microsoft Fakes FakesAssemblies/ # GhostDoc plugin setting file *.GhostDoc.xml # Node.js Tools for Visual Studio .ntvs_analysis.dat node_modules/ # Visual Studio 6 build log *.plg # Visual Studio 6 workspace options file *.opt # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) *.vbw # Visual Studio LightSwitch build output **/*.HTMLClient/GeneratedArtifacts **/*.DesktopClient/GeneratedArtifacts **/*.DesktopClient/ModelManifest.xml **/*.Server/GeneratedArtifacts **/*.Server/ModelManifest.xml _Pvt_Extensions # Paket dependency manager .paket/paket.exe paket-files/ # FAKE - F# Make .fake/ # JetBrains Rider .idea/ *.sln.iml # CodeRush .cr/ # Python Tools for Visual Studio (PTVS) __pycache__/ *.pyc # Cake - Uncomment if you are using it # tools/** # !tools/packages.config # Tabs Studio *.tss # Telerik's JustMock configuration file *.jmconfig # BizTalk build output *.btp.cs *.btm.cs *.odx.cs *.xsd.cs # OpenCover UI analysis results OpenCover/ # Azure Stream Analytics local run output ASALocalRun/ # MSBuild Binary and Structured Log *.binlog # NVidia Nsight GPU debugger configuration file *.nvuser # MFractors (Xamarin productivity tool) working folder .mfractor/ ================================================ FILE: CustomAnalysisRules.Test.ruleset ================================================  ================================================ FILE: CustomAnalysisRules.ruleset ================================================  ================================================ FILE: Directory.Build.props ================================================ true Full 7.3 true false $(EnableSourceLink) true true true $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb false $(MSBuildThisFileDirectory)\CustomAnalysisRules.Test.ruleset true $(MSBuildThisFileDirectory)\CustomAnalysisRules.ruleset ================================================ FILE: LICENSE ================================================ MIT License Copyright (c) 2019 James231 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ # Start Menu Manager [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=MLD56V6HQWCKU&source=url) Windows 10 App to improve you productivity with shortcuts. See the features below: :star: :star: :star: And if you like it ... please star it! :star: :star: :star: Introduction Video: [](https://youtu.be/22APfw-ZSxI) ### Add Shorcuts to Start Menu The app lets you add any kind of shortcut to the Start Menu: - Website Shorcuts - Software Shorcuts - File Shorcuts - Folder Shorcuts - Shorcuts to run Commands/Scripts - 'Group' Shortcuts which open multiple things at the same time ### Add Shortcuts Anywhere Once created, those shorcuts can be moved or added elsewhere. They can be pinned to the Start Menu, added to the Taskbar, added to your Desktop, or put anywhere you like. ### Fixes Windows 10 Bugs Windows 10 Search is buggy and inconsistent. Sometimes you might type in the exact name of an app, but get redirected to Bing search results inside a web brower. Start Menu Manager fixes this. All shorctuts are treated like apps so they get priority in Windows 10 Search and appear at the top of the search results. ### Additional Features - Clean modern Graphical Interface with light/dark themes. - Want an icon for your shortcut? The app can extract images from your favorite websites to use as shortcut icons. - Or provide custom icons as `.ico` files. - Shortcuts can be saved to JSON format so you can copy them between devices. - You can also generate the shortcuts from JSON using a terminal to avoid the GUI. - If you don't like it, uninstallation removes all shortcuts and leaves no 'junk' behind. - No performance loss as no background processes are used. Apps will start with an almost unnoticable overhead. ## Screenshots Click for full size. [](https://cdn.jam-es.com/img/start-menu-manager/screen1.png) [](https://cdn.jam-es.com/img/start-menu-manager/screen2.png) [](https://cdn.jam-es.com/img/start-menu-manager/screen3.png) ## Installation Requires Windows 10 with recent updates. **Disclaimer:** The app needs to run with Administrator privileges, so it can access the directories to place the shortcuts. If you don't have Administrator privileges, then it won't work. 1. Go to the [GitHub Releases page](https://github.com/James231/Start-Menu-Manager/releases). 2. Scroll Down and download the `.msi` file in the 'Assets' section. 3. Run the installer to install the software. ## How to Use It should be intuitive from the app, but just in case ... 1. Open the 'Start Menu Manager' app through the Start Menu. 2. Click the 'Add Shortcut' button to begin creating a shorcut. 3. Change the 'Shortcut Name'. This will be the name which appears in the Start Menu and Windows Search. 4. Change the 'Shortcut Type' to the kind of shortcut you want to create. And fill in the details for that type. E.g. Set the 'Website Url' for Web shortcuts. 5. Next to 'Icon' press 'Select from Website' to pick an icon from your favorite website. 6. Create as many shortcuts as you want in the same way. 7. Press 'Generate' to create the shortcuts. You'll see them added to the start menu under 'Recently Added'. **Optional:** 8. In the Start Menu, right click on the shortcut to pin it, or add it to the Taskbar. 9. Naviagate to the Start Menu folder through the App Settings and copy the shortcut to wherever you want it. **Note:** When generating the shorcuts, icons might not immediatley be displayed correctly in the Start Menu. This is a bug with Windows. One fix is to look in the 'Display' settings in the Windows 10 Settings App. Change the 'Scale and Layout' percentage, wait a few seconds, then change it back again. ## Uninstall Open the 'Apps & Features' page in the Windows 10 Settings app. Select 'Start Menu Manager' and select 'Uninstall'. Everything is removed, including the shorctuts you created with the tool. ## Building the App from Source If you want to get your hands dirty you can build from the source code. Just clone the repository and open the solution (`.sln`) in Visual Studio 2019 or later. The `StartMenuManager.GUI` project contains the main WPF application. `StartMenuManager.Builder` is a console app which creates the shorcuts a from JSON file. `StartMenuManager.Runner` is a console app used to run the Shortcuts when they are clicked. There are a few other class libraries, a project which acts as an uninstallation step, and an Wix installer project. VS may prompt you to open as an administrator, since running the app requires those privileges. Once built, the various console apps (`.exe` files with `.dll`s) need to be put in the correct locations relative to each other. See the `Program Files` of an installed version of the app to see the correct setup. ## License This code is released under MIT license. This means you can use this for whatever you want. Modify, distribute, sell, fork, and use this as much as you like. Both for personal and commercial use. I hold no responsibility if anything goes wrong. If you use this, you don't need to refer to this repo, or give me any kind of credit but it would be appreciated. At least a :star: would be nice. It took a lot of work to make this available for free. If you are feeling more generous, perhaps you could consider donating? [![paypal](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=MLD56V6HQWCKU&source=url) ## Contributing Pull Requests are welcome. But, note that by creating a pull request you are giving me permission to merge your code and release it under the MIT license mentioned above. At no point will you be able to withdraw merged code from the repository, or change the license under which it has been made available. ## References This wouldn't have been possible without ... [Material Design In Xaml](http://materialdesigninxaml.net/) - The WPF styles used in this app. [AvalonEdit](http://avalonedit.net/) - The code editor WPF control used for the JSON editing in the app. [AvalonEditHighlightingThemes](https://github.com/Dirkster99/AvalonEditHighlightingThemes) - Implementation of Themes in AvalonEdit. Used for light/dark JSON editing themes. [FontAwesome.WPF](https://www.nuget.org/packages/FontAwesome.WPF/) - Only used for the loading spinner on the Icon Extractor page. [Json.NET](https://www.newtonsoft.com/json) - JSON serializer. [JsonSubTypes](https://www.newtonsoft.com/json) - JSON SubType implementation for Json.NET. [Wix Toolset](https://wixtoolset.org/) - Used to create the `.msi` installer. ... and obvious credit to Microsoft for C#, WPF, .NET, and the best OS in existence :) ================================================ FILE: StartMenuManager.sln ================================================  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.30330.147 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HL", "src\HL\HL.csproj", "{3DFE9408-3EC2-45F6-B814-ACA60A4DA722}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StartMenuManager.Builder", "src\StartMenuManager.Builder\StartMenuManager.Builder.csproj", "{72692F58-2690-4677-A87B-A686BCAA6FF2}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StartMenuManager.Core", "src\StartMenuManager.Core\StartMenuManager.Core.csproj", "{03E687E5-87C9-4234-86F9-1E746E428764}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StartMenuManager.GUI", "src\StartMenuManager.GUI\StartMenuManager.GUI.csproj", "{AB31D486-50B4-4FF1-9E2C-3D8A29FB8EF4}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StartMenuManager.PreUninstall", "src\StartMenuManager.PreUninstall\StartMenuManager.PreUninstall.csproj", "{E9C16107-0F20-4B36-A65F-54D4290736AB}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StartMenuManager.Runner", "src\StartMenuManager.Runner\StartMenuManager.Runner.csproj", "{567580BE-01CE-420C-86F5-1E91EF50BEEE}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TextEditLib", "src\TextEditLib\TextEditLib.csproj", "{3BAB726C-8CFA-4631-80F3-FB05D3CE2D78}" EndProject Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "StartMenuManager.GUI.Installer", "src\StartMenuManager.GUI.Installer\StartMenuManager.GUI.Installer.wixproj", "{B7CBB2B3-65E2-44FB-AAD6-9BD76884D09D}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {3DFE9408-3EC2-45F6-B814-ACA60A4DA722}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3DFE9408-3EC2-45F6-B814-ACA60A4DA722}.Debug|Any CPU.Build.0 = Debug|Any CPU {3DFE9408-3EC2-45F6-B814-ACA60A4DA722}.Debug|x86.ActiveCfg = Debug|Any CPU {3DFE9408-3EC2-45F6-B814-ACA60A4DA722}.Debug|x86.Build.0 = Debug|Any CPU {3DFE9408-3EC2-45F6-B814-ACA60A4DA722}.Release|Any CPU.ActiveCfg = Release|Any CPU {3DFE9408-3EC2-45F6-B814-ACA60A4DA722}.Release|Any CPU.Build.0 = Release|Any CPU {3DFE9408-3EC2-45F6-B814-ACA60A4DA722}.Release|x86.ActiveCfg = Release|Any CPU {3DFE9408-3EC2-45F6-B814-ACA60A4DA722}.Release|x86.Build.0 = Release|Any CPU {72692F58-2690-4677-A87B-A686BCAA6FF2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {72692F58-2690-4677-A87B-A686BCAA6FF2}.Debug|Any CPU.Build.0 = Debug|Any CPU {72692F58-2690-4677-A87B-A686BCAA6FF2}.Debug|x86.ActiveCfg = Debug|Any CPU {72692F58-2690-4677-A87B-A686BCAA6FF2}.Debug|x86.Build.0 = Debug|Any CPU {72692F58-2690-4677-A87B-A686BCAA6FF2}.Release|Any CPU.ActiveCfg = Release|Any CPU {72692F58-2690-4677-A87B-A686BCAA6FF2}.Release|Any CPU.Build.0 = Release|Any CPU {72692F58-2690-4677-A87B-A686BCAA6FF2}.Release|x86.ActiveCfg = Release|Any CPU {72692F58-2690-4677-A87B-A686BCAA6FF2}.Release|x86.Build.0 = Release|Any CPU {03E687E5-87C9-4234-86F9-1E746E428764}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {03E687E5-87C9-4234-86F9-1E746E428764}.Debug|Any CPU.Build.0 = Debug|Any CPU {03E687E5-87C9-4234-86F9-1E746E428764}.Debug|x86.ActiveCfg = Debug|Any CPU {03E687E5-87C9-4234-86F9-1E746E428764}.Debug|x86.Build.0 = Debug|Any CPU {03E687E5-87C9-4234-86F9-1E746E428764}.Release|Any CPU.ActiveCfg = Release|Any CPU {03E687E5-87C9-4234-86F9-1E746E428764}.Release|Any CPU.Build.0 = Release|Any CPU {03E687E5-87C9-4234-86F9-1E746E428764}.Release|x86.ActiveCfg = Release|Any CPU {03E687E5-87C9-4234-86F9-1E746E428764}.Release|x86.Build.0 = Release|Any CPU {AB31D486-50B4-4FF1-9E2C-3D8A29FB8EF4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {AB31D486-50B4-4FF1-9E2C-3D8A29FB8EF4}.Debug|Any CPU.Build.0 = Debug|Any CPU {AB31D486-50B4-4FF1-9E2C-3D8A29FB8EF4}.Debug|x86.ActiveCfg = Debug|Any CPU {AB31D486-50B4-4FF1-9E2C-3D8A29FB8EF4}.Debug|x86.Build.0 = Debug|Any CPU {AB31D486-50B4-4FF1-9E2C-3D8A29FB8EF4}.Release|Any CPU.ActiveCfg = Release|Any CPU {AB31D486-50B4-4FF1-9E2C-3D8A29FB8EF4}.Release|Any CPU.Build.0 = Release|Any CPU {AB31D486-50B4-4FF1-9E2C-3D8A29FB8EF4}.Release|x86.ActiveCfg = Release|Any CPU {AB31D486-50B4-4FF1-9E2C-3D8A29FB8EF4}.Release|x86.Build.0 = Release|Any CPU {E9C16107-0F20-4B36-A65F-54D4290736AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E9C16107-0F20-4B36-A65F-54D4290736AB}.Debug|Any CPU.Build.0 = Debug|Any CPU {E9C16107-0F20-4B36-A65F-54D4290736AB}.Debug|x86.ActiveCfg = Debug|Any CPU {E9C16107-0F20-4B36-A65F-54D4290736AB}.Debug|x86.Build.0 = Debug|Any CPU {E9C16107-0F20-4B36-A65F-54D4290736AB}.Release|Any CPU.ActiveCfg = Release|Any CPU {E9C16107-0F20-4B36-A65F-54D4290736AB}.Release|Any CPU.Build.0 = Release|Any CPU {E9C16107-0F20-4B36-A65F-54D4290736AB}.Release|x86.ActiveCfg = Release|Any CPU {E9C16107-0F20-4B36-A65F-54D4290736AB}.Release|x86.Build.0 = Release|Any CPU {567580BE-01CE-420C-86F5-1E91EF50BEEE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {567580BE-01CE-420C-86F5-1E91EF50BEEE}.Debug|Any CPU.Build.0 = Debug|Any CPU {567580BE-01CE-420C-86F5-1E91EF50BEEE}.Debug|x86.ActiveCfg = Debug|Any CPU {567580BE-01CE-420C-86F5-1E91EF50BEEE}.Debug|x86.Build.0 = Debug|Any CPU {567580BE-01CE-420C-86F5-1E91EF50BEEE}.Release|Any CPU.ActiveCfg = Release|Any CPU {567580BE-01CE-420C-86F5-1E91EF50BEEE}.Release|Any CPU.Build.0 = Release|Any CPU {567580BE-01CE-420C-86F5-1E91EF50BEEE}.Release|x86.ActiveCfg = Release|Any CPU {567580BE-01CE-420C-86F5-1E91EF50BEEE}.Release|x86.Build.0 = Release|Any CPU {3BAB726C-8CFA-4631-80F3-FB05D3CE2D78}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3BAB726C-8CFA-4631-80F3-FB05D3CE2D78}.Debug|Any CPU.Build.0 = Debug|Any CPU {3BAB726C-8CFA-4631-80F3-FB05D3CE2D78}.Debug|x86.ActiveCfg = Debug|Any CPU {3BAB726C-8CFA-4631-80F3-FB05D3CE2D78}.Debug|x86.Build.0 = Debug|Any CPU {3BAB726C-8CFA-4631-80F3-FB05D3CE2D78}.Release|Any CPU.ActiveCfg = Release|Any CPU {3BAB726C-8CFA-4631-80F3-FB05D3CE2D78}.Release|Any CPU.Build.0 = Release|Any CPU {3BAB726C-8CFA-4631-80F3-FB05D3CE2D78}.Release|x86.ActiveCfg = Release|Any CPU {3BAB726C-8CFA-4631-80F3-FB05D3CE2D78}.Release|x86.Build.0 = Release|Any CPU {B7CBB2B3-65E2-44FB-AAD6-9BD76884D09D}.Debug|Any CPU.ActiveCfg = Debug|x86 {B7CBB2B3-65E2-44FB-AAD6-9BD76884D09D}.Debug|x86.ActiveCfg = Debug|x86 {B7CBB2B3-65E2-44FB-AAD6-9BD76884D09D}.Debug|x86.Build.0 = Debug|x86 {B7CBB2B3-65E2-44FB-AAD6-9BD76884D09D}.Release|Any CPU.ActiveCfg = Release|x86 {B7CBB2B3-65E2-44FB-AAD6-9BD76884D09D}.Release|x86.ActiveCfg = Release|x86 {B7CBB2B3-65E2-44FB-AAD6-9BD76884D09D}.Release|x86.Build.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {9B76E47D-2E1B-4E6E-B7D2-7D9C00328767} EndGlobalSection EndGlobal ================================================ FILE: src/HL/AssemblyInfo.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- using System.Windows; #pragma warning disable [assembly: ThemeInfo( ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located //(used if a resource is not found in the page, // or application resource dictionaries) ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located //(used if a resource is not found in the page, // app, or any theme specific resource dictionaries) )] ================================================ FILE: src/HL/HL.csproj ================================================  net4;netcoreapp3.0 true 1.0.4 1.0.4 1.0.4 Open Source Dirkster.HL 2019-2020 This assembly implements a docking layout system for WPF. true https://github.com/Dirkster99/HL https://github.com/Dirkster99/HL Dirkster.HL https://github.com/Dirkster99/HL LICENSE icon.png avalonedit dark-theme light-theme theming highlighting Mutlitargetting NetCore3 and Net 4.0 Designer Designer Designer PreserveNewest ================================================ FILE: src/HL/HighlightingTheme/GlobalStyle.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- #pragma warning disable namespace HL.HighlightingTheme { using HL.Xshtd.interfaces; using System.Windows.Media; /// /// Implements an object that holds general color and style definitions for the /// Editor. These style definitions are usually non-highlighting language specific /// (eg Hyperlink color) and can overwrite existing WPF definition (eg background or /// foreground color) /// public class GlobalStyle : AbstractFreezable, IFreezable { #region fields private string _TypeName; private Color? _Foregroundcolor; private Color? _Backgroundcolor; private Color? _Bordercolor; #endregion fields #region ctors /// /// Construct a named (eg. 'Comment') WordStyle object /// /// public GlobalStyle(string typeName) : this() { this.TypeName = typeName; } /// /// Hidden standard constructor /// protected GlobalStyle() { this.TypeName = string.Empty; _Foregroundcolor = null; _Backgroundcolor = null; _Bordercolor = null; } #endregion ctors #region properties /// /// Typed name of object /// /// (eg 'DefaultStyle', 'NonPrintableCharacter' ..., /// (this is usually the key in a collection of these styles) /// public string TypeName { get { return _TypeName; } set { if (IsFrozen) throw new System.InvalidOperationException("Property is already frozen."); _TypeName = value; } } /// /// Get/set brush definition for the foreground used in this style /// public Color? foregroundcolor { get { return _Foregroundcolor; } set { if (IsFrozen) throw new System.InvalidOperationException("Property is already frozen."); _Foregroundcolor = value; } } /// /// Get/set brush definition for the background used in this style /// public Color? backgroundcolor { get { return _Backgroundcolor; } set { if (IsFrozen) throw new System.InvalidOperationException("Property is already frozen."); _Backgroundcolor = value; } } /// /// Get/set brush definition for the border used in this style /// public Color? bordercolor { get { return _Bordercolor; } set { if (IsFrozen) throw new System.InvalidOperationException("Property is already frozen."); _Bordercolor = value; } } #endregion properties #region methods /// /// Returns a string that represents the current object. /// /// public override string ToString() { return "[" + (string.IsNullOrEmpty(this.TypeName) ? string.Empty : this.TypeName) + "]"; } #endregion methods } } ================================================ FILE: src/HL/HighlightingTheme/SyntaxDefinition.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- #pragma warning disable namespace HL.HighlightingTheme { using HL.Xshtd.interfaces; using ICSharpCode.AvalonEdit.Highlighting; using ICSharpCode.AvalonEdit.Utils; using System; using System.Collections.Generic; /// /// Implements the object that keeps track of each syntax definition reference /// within a highlighting theme definition. /// public class SyntaxDefinition : AbstractFreezable, IFreezable { #region fields string _Name; private readonly Dictionary _NamedHighlightingColors; #endregion fields #region ctors /// /// Class constructor /// public SyntaxDefinition(string paramName) : this() { this._Name = paramName; } /// /// Class constructor /// public SyntaxDefinition() { this.Extensions = new NullSafeCollection(); _NamedHighlightingColors = new Dictionary(); } #endregion ctors #region properties /// /// Gets/Sets the name of the color. /// public string Name { get { return _Name; } set { if (IsFrozen) throw new InvalidOperationException(); _Name = value; } } /// /// Gets the associated extensions. /// public IList Extensions { get; private set; } /// /// Gets an enumeration of all highlighting colors that are defined /// for this highlighting pattern (eg. C#) as part of a highlighting theme (eg 'True Blue'). /// public IEnumerable NamedHighlightingColors { get { return _NamedHighlightingColors.Values; } } #endregion properties #region methods /// /// Returns a string that represents the current object. /// /// public override string ToString() { return "[" + GetType().Name + " " + (string.IsNullOrEmpty(this.Name) ? string.Empty : this.Name) + "]"; } /// /// Gets a named color definition or null. /// /// /// public HighlightingColor ColorGet(string name) { HighlightingColor color; if (_NamedHighlightingColors.TryGetValue(name, out color)) return color; return null; } /// /// Adds another named color definition. /// Exceptions: /// /// key is null. /// /// /// An element with the same key already exists in the System.Collections.Generic.Dictionary`2. /// /// public void ColorAdd(HighlightingColor color) { _NamedHighlightingColors.Add(color.Name, color); } internal void ColorReplace(string name, HighlightingColor themeColor) { _NamedHighlightingColors.Remove(name); _NamedHighlightingColors.Add(name, themeColor); } #endregion methods } } ================================================ FILE: src/HL/Interfaces/IHLTheme.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - © Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- #pragma warning disable namespace HL.Manager { using System.Collections.ObjectModel; using HL.HighlightingTheme; using HL.Xshtd; using HL.Xshtd.interfaces; using ICSharpCode.AvalonEdit.Highlighting; /// /// Defines a highlighting theme which is based on a WPF theme (eg. 'Light') /// with a corresponding set of highlighting definitions (eg. 'XML', 'C#' etc) /// to ensure that highlightings are correct in the contecxt of /// (different background colors) WPF themes. /// public interface IHLTheme { #region properties /// /// Gets the display independent key value that should by unique in an /// overall collection of highlighting themes and should be used for retrieval purposes. /// string Key { get; } /// /// Gets the prefix of the XSHD resources that should be used to lookup /// the actual resource for this theme. /// /// This property is null for a derived highlighting theme since finding its /// base highlighting should by performed through /// and the corresponding property of that entry. /// string HLBasePrefix { get; } /// /// Gets the name of theme (eg. 'Dark' or 'Light' which is used as /// the base of a derived highlighting theme. /// /// This property has the same value as the property /// if the highlighting is GENERIC (since these highlightings come without /// additional theme resources). /// string HLBaseKey { get; } /// /// Gets the prefix of the resource under which a theme resource definition /// file xshTd can be found (eg 'HL.Resources.Themes'). /// string HLThemePrefix { get; } /// /// Gets the file name under which a theme resource definition /// file xshTd can be found (eg 'Dark.xshtd'). /// string HLThemeFileName { get; } /// /// Gets the name of theme (eg. 'Dark', 'Light' or 'True Blue' for display purposes in the UI. /// string DisplayName { get; } /// /// Gets a copy of all highlightings defined in this object. /// ReadOnlyCollection HighlightingDefinitions { get; } /// /// Gets the theme highlighting definition for this theme /// or null (highlighting definition is generic and not based on a theme). /// IHighlightingThemeDefinition HlTheme { get; } /// /// Gets/sets whether built-in themes have already been registered or not /// Use this to avoid registration of built-in themes twice for one and the /// same highlighting theme. /// bool IsBuiltInThemesRegistered { get; set; } #endregion properties #region methods /// /// Gets the highlighting definition by name, or null if it is not found. /// IHighlightingDefinition GetDefinition(string name); /// /// Gets a highlighting definition by extension. /// Returns null if the definition is not found. /// IHighlightingDefinition GetDefinitionByExtension(string extension); /// /// Registers a highlighting definition. /// /// The name to register the definition with. /// The file extensions to register the definition for. /// The highlighting definition. void RegisterHighlighting(string name, string[] extensions, IHighlightingDefinition highlighting); /// /// Gets the highlighting theme definition by name, or null if it is not found. /// /// SyntaxDefinition GetThemeDefinition(string highlightingName); /// /// Converts a XSHD reference from namespace prefix and themename /// into a object and returns it. /// /// /// /// XhstdThemeDefinition ResolveHighLightingTheme(string hLPrefix, string hLThemeName); #endregion methods } } ================================================ FILE: src/HL/Interfaces/IThemedHighlightingManager.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- #pragma warning disable namespace HL.Interfaces { using HL.Manager; using HL.Xshtd.interfaces; using ICSharpCode.AvalonEdit.Highlighting; using System; using System.Collections.ObjectModel; /// /// Defines a Highlighting Manager that associates syntax highlighting definitions with file extentions /// (*.cs -> 'C#') with consideration of the current WPF App theme /// /// Extension App Theme SyntaxHighlighter /// (*.cs + 'Dark') -> 'C#' (with color definitions for 'Dark') /// public interface IThemedHighlightingManager : IHighlightingDefinitionReferenceResolver, IHighlightingThemeDefinitionReferenceResolver { #region properties /// /// Gets the current highlighting theme (eg 'Light' or 'Dark') that should be used as /// a base for the syntax highlighting in AvalonEdit. /// IHLTheme CurrentTheme { get; } #endregion properties #region methods /// /// Gets a copy of all highlightings. /// ReadOnlyCollection HighlightingDefinitions { get; } /// /// Gets a highlighting definition by extension. /// Returns null if the definition is not found. /// IHighlightingDefinition GetDefinitionByExtension(string extension); /// /// Registers a highlighting definition for the . /// /// The name to register the definition with. /// The file extensions to register the definition for. /// The highlighting definition. void RegisterHighlighting(string name, string[] extensions, IHighlightingDefinition highlighting); /// /// Registers a highlighting definition. /// /// The name to register the definition with. /// The file extensions to register the definition for. /// A function that loads the highlighting definition. void RegisterHighlighting(string name, string[] extensions, Func lazyLoadedHighlighting); /// /// Resets the highlighting theme based on the name of the WPF App Theme /// (eg: WPF APP Theme 'Dark' -> Resolve highlighting 'C#' to 'Dark'->'C#') /// /// Throws an if the WPF APP theme is not known. /// /// void SetCurrentTheme(string name); #endregion methods } } ================================================ FILE: src/HL/LICENSE ================================================ Copyright 2019-2020 Dirkster99 MIT License (https://opensource.org/licenses/MIT) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: src/HL/Manager/BusyManager.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- #pragma warning disable namespace HL.Manager { using System; using System.Collections.Generic; /// /// This class is used to prevent stack overflows by representing a 'busy' flag /// that prevents reentrance when another call is running. /// However, using a simple 'bool busy' is not thread-safe, so we use a /// thread-static BusyManager. /// internal static class BusyManager { [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1815:OverrideEqualsAndOperatorEqualsOnValueTypes")] [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible", Justification = "Should always be used with 'var'")] public struct BusyLock : IDisposable { public static readonly BusyLock Failed = new BusyLock(null); readonly List objectList; internal BusyLock(List objectList) { this.objectList = objectList; } public bool Success { get { return objectList != null; } } public void Dispose() { if (objectList != null) { objectList.RemoveAt(objectList.Count - 1); } } } [ThreadStatic] static List _activeObjects; public static BusyLock Enter(object obj) { List activeObjects = _activeObjects; if (activeObjects == null) activeObjects = _activeObjects = new List(); for (int i = 0; i < activeObjects.Count; i++) { if (activeObjects[i] == obj) return BusyLock.Failed; } activeObjects.Add(obj); return new BusyLock(activeObjects); } } } ================================================ FILE: src/HL/Manager/DefaultHighlightingManager.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- #pragma warning disable namespace HL.Manager { using HL.HighlightingTheme; using HL.Resources; using ICSharpCode.AvalonEdit.Highlighting; using System; using System.Diagnostics; using System.IO; using System.Xml; /// /// Implements a default highlighting manager for /// AvalonEdit based themable syntax highlighting definitions. /// internal sealed class DefaultHighlightingManager : ThemedHighlightingManager { #region ctors /// /// Static class constructor /// static DefaultHighlightingManager() { var defaultManager = new DefaultHighlightingManager(); var theme = new HLTheme("Dark", "Light", "Dark", HL_THEMES_NAMESPACE_ROOT, "Dark.xshtd", defaultManager); defaultManager.ThemedHighlightingAdd(theme.Key, theme); theme = new HLTheme("Light", HL_GENERIC_NAMESPACE_ROOT, "Light"); defaultManager.ThemedHighlightingAdd(theme.Key, theme); // Setup default theme without registration of Highlightings defaultManager.SetCurrentThemeInternal(theme.Key); theme = new HLTheme("TrueBlue", "Light", "True Blue", HL_THEMES_NAMESPACE_ROOT, "TrueBlue.xshtd", defaultManager); defaultManager.ThemedHighlightingAdd(theme.Key, theme); theme = new HLTheme("VS2019_Dark", "Light", "VS2019 Dark", HL_THEMES_NAMESPACE_ROOT, "VS2019_Dark.xshtd", defaultManager); defaultManager.ThemedHighlightingAdd(theme.Key, theme); HLResources.RegisterBuiltInHighlightings(defaultManager, defaultManager.CurrentTheme); Instance = defaultManager; } /// /// Default class constructor /// public DefaultHighlightingManager() : base() { } #endregion ctors /// /// Gets an instance of a object. /// public new static readonly DefaultHighlightingManager Instance; /// /// Registering a built-in highlighting including highlighting themes (if any). /// /// /// /// /// internal void RegisterHighlighting(IHLTheme theme, string name, string[] extensions, string resourceName) { try { #if DEBUG // don't use lazy-loading in debug builds, show errors immediately ICSharpCode.AvalonEdit.Highlighting.Xshd.XshdSyntaxDefinition xshd; using (Stream s = HLResources.OpenStream(GetPrefix(CurrentTheme.HLBaseKey), resourceName)) { using (XmlTextReader reader = new XmlTextReader(s)) { xshd = HighlightingLoader.LoadXshd(reader, false); } } Debug.Assert(name == xshd.Name); if (extensions != null) Debug.Assert(System.Linq.Enumerable.SequenceEqual(extensions, xshd.Extensions)); else Debug.Assert(xshd.Extensions.Count == 0); var hlTheme = theme.HlTheme; SyntaxDefinition themedHighlights = null; if (hlTheme != null) { themedHighlights = hlTheme.GetNamedSyntaxDefinition(name); } // round-trip xshd: // string resourceFileName = Path.Combine(Path.GetTempPath(), resourceName); // using (XmlTextWriter writer = new XmlTextWriter(resourceFileName, System.Text.Encoding.UTF8)) { // writer.Formatting = Formatting.Indented; // new Xshd.SaveXshdVisitor(writer).WriteDefinition(xshd); // } // using (FileStream fs = File.Create(resourceFileName + ".bin")) { // new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter().Serialize(fs, xshd); // } // using (FileStream fs = File.Create(resourceFileName + ".compiled")) { // new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter().Serialize(fs, Xshd.HighlightingLoader.Load(xshd, this)); // } base.RegisterHighlighting(name, extensions, HighlightingLoader.Load(themedHighlights, xshd, this)); #else base.RegisterHighlighting(name, extensions, LoadHighlighting(theme, name, resourceName)); #endif } catch (HighlightingDefinitionInvalidException ex) { throw new InvalidOperationException("The built-in highlighting '" + name + "' is invalid.", ex); } } /// /// Gets a function that is used to load highlighting definition in a delayed/defered way /// (usually active only when 'Release' is configured). /// /// /// /// /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "LoadHighlighting is used only in release builds")] Func LoadHighlighting(IHLTheme theme, string name, string resourceName) { Func func = delegate { ICSharpCode.AvalonEdit.Highlighting.Xshd.XshdSyntaxDefinition xshd; using (Stream s = HLResources.OpenStream(GetPrefix(CurrentTheme.HLBaseKey), resourceName)) { using (XmlTextReader reader = new XmlTextReader(s)) { // in release builds, skip validating the built-in highlightings xshd = HighlightingLoader.LoadXshd(reader, true); } } var hlTheme = theme.HlTheme; SyntaxDefinition themedHighlights = null; if (hlTheme != null) { themedHighlights = hlTheme.GetNamedSyntaxDefinition(name); } return HighlightingLoader.Load(themedHighlights, xshd, this); }; return func; } } } ================================================ FILE: src/HL/Manager/DelayLoadedHighlightingDefinition.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- #pragma warning disable namespace HL.Manager { using ICSharpCode.AvalonEdit.Highlighting; using System; using System.Collections.Generic; internal sealed class DelayLoadedHighlightingDefinition : IHighlightingDefinition { readonly object lockObj = new object(); readonly string name; Func lazyLoadingFunction; IHighlightingDefinition definition; Exception storedException; public DelayLoadedHighlightingDefinition(string name, Func lazyLoadingFunction) { this.name = name; this.lazyLoadingFunction = lazyLoadingFunction; } public string Name { get { if (name != null) return name; else return GetDefinition().Name; } } [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "The exception will be rethrown")] IHighlightingDefinition GetDefinition() { Func func; lock (lockObj) { if (this.definition != null) return this.definition; func = this.lazyLoadingFunction; } Exception exception = null; IHighlightingDefinition def = null; try { using (var busyLock = BusyManager.Enter(this)) { if (!busyLock.Success) throw new InvalidOperationException("Tried to create delay-loaded highlighting definition recursively. Make sure the are no cyclic references between the highlighting definitions."); def = func(); } if (def == null) throw new InvalidOperationException("Function for delay-loading highlighting definition returned null"); } catch (Exception ex) { exception = ex; } lock (lockObj) { this.lazyLoadingFunction = null; if (this.definition == null && this.storedException == null) { this.definition = def; this.storedException = exception; } if (this.storedException != null) throw new HighlightingDefinitionInvalidException("Error delay-loading highlighting definition", this.storedException); return this.definition; } } public HighlightingRuleSet MainRuleSet { get { return GetDefinition().MainRuleSet; } } public HighlightingRuleSet GetNamedRuleSet(string name) { return GetDefinition().GetNamedRuleSet(name); } public HighlightingColor GetNamedColor(string name) { return GetDefinition().GetNamedColor(name); } public IEnumerable NamedHighlightingColors { get { return GetDefinition().NamedHighlightingColors; } } public override string ToString() { return this.Name; } public IDictionary Properties { get { return GetDefinition().Properties; } } } } ================================================ FILE: src/HL/Manager/ExtensionMethods.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- #pragma warning disable namespace HL.Manager { using System; using System.Collections.Generic; using System.Diagnostics; //// using System.Windows; //// using System.Windows.Controls; //// using System.Windows.Media; using System.Xml; static class ExtensionMethods { #region Epsilon / IsClose / CoerceValue /// /// Epsilon used for IsClose() implementations. /// We can use up quite a few digits in front of the decimal point (due to visual positions being relative to document origin), /// and there's no need to be too accurate (we're dealing with pixels here), /// so we will use the value 0.01. /// Previosly we used 1e-8 but that was causing issues: /// http://community.sharpdevelop.net/forums/t/16048.aspx /// public const double Epsilon = 0.01; /// /// Returns true if the doubles are close (difference smaller than 0.01). /// public static bool IsClose(this double d1, double d2) { if (d1 == d2) // required for infinities return true; return Math.Abs(d1 - d2) < Epsilon; } //// /// //// /// Returns true if the doubles are close (difference smaller than 0.01). //// /// //// public static bool IsClose(this Size d1, Size d2) //// { //// return IsClose(d1.Width, d2.Width) && IsClose(d1.Height, d2.Height); //// } //// //// /// //// /// Returns true if the doubles are close (difference smaller than 0.01). //// /// //// public static bool IsClose(this Vector d1, Vector d2) //// { //// return IsClose(d1.X, d2.X) && IsClose(d1.Y, d2.Y); //// } /// /// Forces the value to stay between mininum and maximum. /// /// minimum, if value is less than minimum. /// Maximum, if value is greater than maximum. /// Otherwise, value. public static double CoerceValue(this double value, double minimum, double maximum) { return Math.Max(Math.Min(value, maximum), minimum); } /// /// Forces the value to stay between mininum and maximum. /// /// minimum, if value is less than minimum. /// Maximum, if value is greater than maximum. /// Otherwise, value. public static int CoerceValue(this int value, int minimum, int maximum) { return Math.Max(Math.Min(value, maximum), minimum); } #endregion //// #region CreateTypeface //// /// //// /// Creates typeface from the framework element. //// /// //// public static Typeface CreateTypeface(this FrameworkElement fe) //// { //// return new Typeface((FontFamily)fe.GetValue(TextBlock.FontFamilyProperty), //// (FontStyle)fe.GetValue(TextBlock.FontStyleProperty), //// (FontWeight)fe.GetValue(TextBlock.FontWeightProperty), //// (FontStretch)fe.GetValue(TextBlock.FontStretchProperty)); //// } //// #endregion #region AddRange / Sequence public static void AddRange(this ICollection collection, IEnumerable elements) { foreach (T e in elements) collection.Add(e); } /// /// Creates an IEnumerable with a single value. /// public static IEnumerable Sequence(T value) { yield return value; } #endregion #region XML reading /// /// Gets the value of the attribute, or null if the attribute does not exist. /// public static string GetAttributeOrNull(this XmlElement element, string attributeName) { XmlAttribute attr = element.GetAttributeNode(attributeName); return attr != null ? attr.Value : null; } /// /// Gets the value of the attribute as boolean, or null if the attribute does not exist. /// public static bool? GetBoolAttribute(this XmlElement element, string attributeName) { XmlAttribute attr = element.GetAttributeNode(attributeName); return attr != null ? (bool?)XmlConvert.ToBoolean(attr.Value) : null; } /// /// Gets the value of the attribute as boolean, or null if the attribute does not exist. /// public static bool? GetBoolAttribute(this XmlReader reader, string attributeName) { string attributeValue = reader.GetAttribute(attributeName); if (attributeValue == null) return null; else return XmlConvert.ToBoolean(attributeValue); } #endregion //// #region DPI independence //// public static Rect TransformToDevice(this Rect rect, Visual visual) //// { //// Matrix matrix = PresentationSource.FromVisual(visual).CompositionTarget.TransformToDevice; //// return Rect.Transform(rect, matrix); //// } //// //// public static Rect TransformFromDevice(this Rect rect, Visual visual) //// { //// Matrix matrix = PresentationSource.FromVisual(visual).CompositionTarget.TransformFromDevice; //// return Rect.Transform(rect, matrix); //// } //// //// public static Size TransformToDevice(this Size size, Visual visual) //// { //// Matrix matrix = PresentationSource.FromVisual(visual).CompositionTarget.TransformToDevice; //// return new Size(size.Width * matrix.M11, size.Height * matrix.M22); //// } //// //// public static Size TransformFromDevice(this Size size, Visual visual) //// { //// Matrix matrix = PresentationSource.FromVisual(visual).CompositionTarget.TransformFromDevice; //// return new Size(size.Width * matrix.M11, size.Height * matrix.M22); //// } //// //// public static Point TransformToDevice(this Point point, Visual visual) //// { //// Matrix matrix = PresentationSource.FromVisual(visual).CompositionTarget.TransformToDevice; //// return new Point(point.X * matrix.M11, point.Y * matrix.M22); //// } //// //// public static Point TransformFromDevice(this Point point, Visual visual) //// { //// Matrix matrix = PresentationSource.FromVisual(visual).CompositionTarget.TransformFromDevice; //// return new Point(point.X * matrix.M11, point.Y * matrix.M22); //// } //// #endregion #region System.Drawing <-> WPF conversions //// public static System.Drawing.Point ToSystemDrawing(this Point p) //// { //// return new System.Drawing.Point((int)p.X, (int)p.Y); //// } //// //// public static Point ToWpf(this System.Drawing.Point p) //// { //// return new Point(p.X, p.Y); //// } //// //// public static Size ToWpf(this System.Drawing.Size s) //// { //// return new Size(s.Width, s.Height); //// } //// //// public static Rect ToWpf(this System.Drawing.Rectangle rect) //// { //// return new Rect(rect.Location.ToWpf(), rect.Size.ToWpf()); //// } #endregion //// public static IEnumerable VisualAncestorsAndSelf(this DependencyObject obj) //// { //// while (obj != null) //// { //// yield return obj; //// if (obj is Visual || obj is System.Windows.Media.Media3D.Visual3D) //// { //// obj = VisualTreeHelper.GetParent(obj); //// } //// else if (obj is FrameworkContentElement) //// { //// // When called with a non-visual such as a TextElement, walk up the //// // logical tree instead. //// obj = ((FrameworkContentElement)obj).Parent; //// } //// else //// { //// break; //// } //// } //// } //// //// [Conditional("DEBUG")] //// public static void CheckIsFrozen(Freezable f) //// { //// if (f != null && !f.IsFrozen) //// Debug.WriteLine("Performance warning: Not frozen: " + f.ToString()); //// } [Conditional("DEBUG")] public static void Log(bool condition, string format, params object[] args) { if (condition) { string output = DateTime.Now.ToString("hh:MM:ss") + ": " + string.Format(format, args) + Environment.NewLine + Environment.StackTrace; Console.WriteLine(output); Debug.WriteLine(output); } } } } ================================================ FILE: src/HL/Manager/HLTheme.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- #pragma warning disable namespace HL.Manager { using HL.HighlightingTheme; using HL.Resources; using HL.Xshtd; using HL.Xshtd.interfaces; using ICSharpCode.AvalonEdit.Highlighting; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.IO; using System.Linq; using System.Xml; /// /// Implements a highlighting theme which is based on a WPF theme (eg. 'Light') /// with a corresponding set of highlighting definitions (eg. 'XML', 'C#' etc) /// to ensure that highlightings are correct in the contecxt of /// (different background colors) WPF themes. /// internal class HLTheme : IHLTheme { #region fields private readonly object lockObj = new object(); private Dictionary highlightingsByName = new Dictionary(); private Dictionary highlightingsByExtension = new Dictionary(StringComparer.OrdinalIgnoreCase); private List allHighlightings = new List(); private bool _HLThemeIsInitialized; private XhstdThemeDefinition _xshtd; private XmlHighlightingThemeDefinition _hlTheme; private readonly IHighlightingThemeDefinitionReferenceResolver _hLThemeResolver; #endregion fields #region ctors /// /// Class constructor for GENERIC highlighting definitions. /// /// Generic highlighting definitions ar usually defined in xshd /// files and stand on their own (do not need additional processing/resources /// to compute highlighting rules and formating information). /// /// /// /// public HLTheme(string paramKey, string paramHLBasePrefix, string paramDisplayName) : this() { Key = paramKey; HLBasePrefix = paramHLBasePrefix; // This Highlighting is GENERIC - based on 'itself' HLBaseKey = paramKey; DisplayName = paramDisplayName; } /// /// Class constructor for derived highlighting themes. /// /// Derived highlighting themes have a base highlighting (eg 'Light') /// and an 'overwritting' highlighting themes definition using an xshTd file resource. /// /// /// /// /// /// /// public HLTheme(string paramKey, string paramHLBaseKey, string paramDisplayName, string paramHLThemePrefix, string paramHLThemeName, IHighlightingThemeDefinitionReferenceResolver themeResolver) : this() { Key = paramKey; HLBaseKey = paramHLBaseKey; HLThemePrefix = paramHLThemePrefix; HLThemeFileName = paramHLThemeName; _hLThemeResolver = themeResolver; DisplayName = paramDisplayName; } /// /// Hidden class constructor /// protected HLTheme() { } #endregion ctors #region properties /// /// Gets the display independent key value that should by unique in an /// overall collection of highlighting themes and should be used for retrieval purposes. /// public string Key { get; } /// /// Gets the prefix of the XSHD resources that should be used to lookup /// the actual resource for this theme. /// /// This property is null for a derived highlighting theme since finding its /// base highlighting should by performed through /// and the corresponding property of that entry. /// public string HLBasePrefix { get; } /// /// Gets the name of theme (eg. 'Dark' or 'Light' which is used as /// the base of a derived highlighting theme. /// /// This property has the same value as the property /// if the highlighting is GENERIC (since these highlightings come without /// additional theme resources). /// public string HLBaseKey { get; } /// /// Gets the prefix of the resource under which a theme resource definition /// file xshTd can be found (eg 'HL.Resources.Themes'). /// public string HLThemePrefix { get; } /// /// Gets the file name under which a theme resource definition /// file xshTd can be found (eg 'Dark.xshtd'). /// public string HLThemeFileName { get; } /// /// Gets the name of theme (eg. 'Dark', 'Light' or 'True Blue' for display purposes in the UI. /// public string DisplayName { get; } /// /// Gets an (ordered by Name) list copy of all highlightings defined in this object. /// public ReadOnlyCollection HighlightingDefinitions { get { lock (lockObj) { return Array.AsReadOnly(allHighlightings.OrderBy(x => x.Name).ToArray()); } } } /// /// Gets the theme highlighting definition for this theme /// or null (highlighting definition is generic and not based on a theme). /// public IHighlightingThemeDefinition HlTheme { get { ResolveHighLightingTheme(); return _hlTheme; } } /// /// Gets/sets whether built-in themes have already been registered or not /// Use this to avoid registration of built-in themes twice for one and the /// same highlighting theme. /// public bool IsBuiltInThemesRegistered { get; set; } #endregion properties #region methods /// /// Gets the highlighting definition by name, or null if it is not found. /// public IHighlightingDefinition GetDefinition(string name) { lock (lockObj) { this.ResolveHighLightingTheme(); IHighlightingDefinition rh; if (highlightingsByName.TryGetValue(name, out rh)) return rh; else return null; } } /// /// Gets the highlighting theme definition by name, or null if it is not found. /// public SyntaxDefinition GetThemeDefinition(string highlightingName) { lock (lockObj) { this.ResolveHighLightingTheme(); return _hlTheme.GetNamedSyntaxDefinition(highlightingName); } } /// /// Gets a highlighting definition by extension. /// Returns null if the definition is not found. /// public IHighlightingDefinition GetDefinitionByExtension(string extension) { lock (lockObj) { this.ResolveHighLightingTheme(); IHighlightingDefinition rh; if (highlightingsByExtension.TryGetValue(extension, out rh)) return rh; else return null; } } /// /// Registers a highlighting definition. /// /// The name to register the definition with. /// The file extensions to register the definition for. /// The highlighting definition. public void RegisterHighlighting(string name, string[] extensions, IHighlightingDefinition highlighting) { lock (lockObj) { // Perform an update if this highlighting happens to be available already var itemInList = allHighlightings.FirstOrDefault(i => name == i.Name); if (itemInList != null) allHighlightings.Remove(itemInList); allHighlightings.Add(highlighting); if (name != null) { highlightingsByName[name] = highlighting; } if (extensions != null) { foreach (string ext in extensions) { highlightingsByExtension[ext] = highlighting; } } } } /// /// Loads the highlighting theme for this highlighting definition /// (if an additional theme was configured) /// protected virtual void ResolveHighLightingTheme() { if (_hlTheme != null || _HLThemeIsInitialized == true) return; _HLThemeIsInitialized = true; // Initialize this at most once // Load the highlighting theme and setup converter to XmlHighlightingThemeDefinition _xshtd = ResolveHighLightingTheme(HLThemePrefix, HLThemeFileName); if (_hLThemeResolver == null || _xshtd == null) return; _hlTheme = new XmlHighlightingThemeDefinition(_xshtd, _hLThemeResolver); } /// /// Converts a XSHTD reference from namespace prefix and themename /// into a object and returns it. /// /// /// /// public XhstdThemeDefinition ResolveHighLightingTheme(string hLPrefix, string hLThemeName) { if (string.IsNullOrEmpty(hLPrefix) || string.IsNullOrEmpty(hLThemeName)) return null; using (Stream s = HLResources.OpenStream(hLPrefix, hLThemeName)) { using (XmlTextReader reader = new XmlTextReader(s)) { return HighlightingThemeLoader.LoadXshd(reader, false); } } } #endregion methods } } ================================================ FILE: src/HL/Manager/HighlightingBrush.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- #pragma warning disable namespace HL.Manager { using System; using System.Diagnostics; using System.Reflection; using System.Runtime.Serialization; using System.Windows; using System.Windows.Media; using ICSharpCode.AvalonEdit.Highlighting; using ICSharpCode.AvalonEdit.Rendering; /// /// HighlightingBrush implementation that finds a brush using a resource. /// [Serializable] sealed class SystemColorHighlightingBrush : HighlightingBrush, ISerializable { readonly PropertyInfo property; public SystemColorHighlightingBrush(PropertyInfo property) { Debug.Assert(property.ReflectedType == typeof(SystemColors)); Debug.Assert(typeof(Brush).IsAssignableFrom(property.PropertyType)); this.property = property; } public override Brush GetBrush(ITextRunConstructionContext context) { return (Brush)property.GetValue(null, null); } public override string ToString() { return property.Name; } SystemColorHighlightingBrush(SerializationInfo info, StreamingContext context) { property = typeof(SystemColors).GetProperty(info.GetString("propertyName")); if (property == null) throw new ArgumentException("Error deserializing SystemColorHighlightingBrush"); } void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) { info.AddValue("propertyName", property.Name); } public override bool Equals(object obj) { SystemColorHighlightingBrush other = obj as SystemColorHighlightingBrush; if (other == null) return false; return object.Equals(this.property, other.property); } public override int GetHashCode() { return property.GetHashCode(); } } } ================================================ FILE: src/HL/Manager/HighlightingLoader.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- #pragma warning disable namespace HL.Manager { using HL.HighlightingTheme; using ICSharpCode.AvalonEdit.Highlighting; using ICSharpCode.AvalonEdit.Highlighting.Xshd; using System; using System.Xml; using System.Xml.Schema; /// /// Static class with helper methods to load XSHD highlighting files. /// public static class HighlightingLoader { #region XSHD loading /// /// Lodas a syntax definition from the xml reader. /// public static XshdSyntaxDefinition LoadXshd(XmlReader reader) { return LoadXshd(reader, false); } internal static XshdSyntaxDefinition LoadXshd(XmlReader reader, bool skipValidation) { if (reader == null) throw new ArgumentNullException("reader"); try { reader.MoveToContent(); //// if (reader.NamespaceURI == V2Loader.Namespace) //// { return V2Loader.LoadDefinition(reader, skipValidation); //// } //// else //// { //// return V1Loader.LoadDefinition(reader, skipValidation); //// } } catch (XmlSchemaException ex) { throw WrapException(ex, ex.LineNumber, ex.LinePosition); } catch (XmlException ex) { throw WrapException(ex, ex.LineNumber, ex.LinePosition); } } static Exception WrapException(Exception ex, int lineNumber, int linePosition) { return new HighlightingDefinitionInvalidException(FormatExceptionMessage(ex.Message, lineNumber, linePosition), ex); } internal static string FormatExceptionMessage(string message, int lineNumber, int linePosition) { if (lineNumber <= 0) return message; else return "Error at position (line " + lineNumber + ", column " + linePosition + "):\n" + message; } internal static XmlReader GetValidatingReader(XmlReader input, bool ignoreWhitespace, XmlSchemaSet schemaSet) { XmlReaderSettings settings = new XmlReaderSettings(); settings.CloseInput = true; settings.IgnoreComments = true; settings.IgnoreWhitespace = ignoreWhitespace; if (schemaSet != null) { settings.Schemas = schemaSet; settings.ValidationType = ValidationType.Schema; } return XmlReader.Create(input, settings); } internal static XmlSchemaSet LoadSchemaSet(XmlReader schemaInput) { XmlSchemaSet schemaSet = new XmlSchemaSet(); schemaSet.Add(null, schemaInput); schemaSet.ValidationEventHandler += delegate (object sender, ValidationEventArgs args) { throw new HighlightingDefinitionInvalidException(args.Message); }; return schemaSet; } #endregion #region Load Highlighting from XSHD /// /// Creates a highlighting definition from the XSHD file. /// public static IHighlightingDefinition Load(XshdSyntaxDefinition syntaxDefinition, IHighlightingDefinitionReferenceResolver resolver) { if (syntaxDefinition == null) throw new ArgumentNullException("syntaxDefinition"); return new XmlHighlightingDefinition(syntaxDefinition, resolver); } /// /// Loads a highlighting definition base on a: /// /// /// Themed Highlighting Definition /// (This contains the color definition for a highlighting in this theme) /// /// /// A Highlighting definition /// (This contains the pattern matching and color definitions where the later /// is usually overwritten be a highlighting theme) /// /// An object that can resolve a highlighting definition by its name. /// public static IHighlightingDefinition Load(SyntaxDefinition themedHighlights, XshdSyntaxDefinition syntaxDefinition, IHighlightingDefinitionReferenceResolver resolver ) { if (syntaxDefinition == null) throw new ArgumentNullException("syntaxDefinition"); return new XmlHighlightingDefinition(themedHighlights, syntaxDefinition, resolver); } /// /// Creates a highlighting definition from the XSHD file that is already initialled /// in the instance of the parameter. /// public static IHighlightingDefinition Load(XmlReader reader, IHighlightingDefinitionReferenceResolver resolver) { return Load(LoadXshd(reader), resolver); } #endregion } } ================================================ FILE: src/HL/Manager/HighlightingThemeLoader.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- #pragma warning disable namespace HL.Manager { using HL.Xshtd; using HL.Xshtd.interfaces; using ICSharpCode.AvalonEdit.Highlighting; using System; using System.Xml; using System.Xml.Schema; /// /// Static class with helper methods to load XSHTD highlighting files. /// static class HighlightingThemeLoader { #region XSHD loading /// /// Lodas a syntax definition from the xml reader. /// public static XhstdThemeDefinition LoadXshd(XmlReader reader) { return LoadXshd(reader, false); } internal static XhstdThemeDefinition LoadXshd(XmlReader reader, bool skipValidation) { if (reader == null) throw new ArgumentNullException("reader"); try { reader.MoveToContent(); if (reader.NamespaceURI == XshtdLoader.Namespace) { return XshtdLoader.LoadDefinition(reader, skipValidation); } throw new ArgumentOutOfRangeException(reader.NamespaceURI); } catch (XmlSchemaException ex) { throw WrapException(ex, ex.LineNumber, ex.LinePosition); } catch (XmlException ex) { throw WrapException(ex, ex.LineNumber, ex.LinePosition); } } static Exception WrapException(Exception ex, int lineNumber, int linePosition) { return new HighlightingDefinitionInvalidException(FormatExceptionMessage(ex.Message, lineNumber, linePosition), ex); } internal static string FormatExceptionMessage(string message, int lineNumber, int linePosition) { if (lineNumber <= 0) return message; else return "Error at position (line " + lineNumber + ", column " + linePosition + "):\n" + message; } internal static XmlReader GetValidatingReader(XmlReader input, bool ignoreWhitespace, XmlSchemaSet schemaSet) { XmlReaderSettings settings = new XmlReaderSettings(); settings.CloseInput = true; settings.IgnoreComments = true; settings.IgnoreWhitespace = ignoreWhitespace; if (schemaSet != null) { settings.Schemas = schemaSet; settings.ValidationType = ValidationType.Schema; } return XmlReader.Create(input, settings); } internal static XmlSchemaSet LoadSchemaSet(XmlReader schemaInput) { XmlSchemaSet schemaSet = new XmlSchemaSet(); schemaSet.Add(null, schemaInput); schemaSet.ValidationEventHandler += delegate (object sender, ValidationEventArgs args) { throw new HighlightingDefinitionInvalidException(args.Message); }; return schemaSet; } #endregion #region Load Highlighting from XSHD /// /// Creates a highlighting definition from the XSHD file. /// public static IHighlightingThemeDefinition Load(XhstdThemeDefinition syntaxDefinition, IHighlightingThemeDefinitionReferenceResolver resolver) { if (syntaxDefinition == null) throw new ArgumentNullException("syntaxDefinition"); return new XmlHighlightingThemeDefinition(syntaxDefinition, resolver); } /// /// Creates a highlighting definition from the XSHD file. /// public static IHighlightingThemeDefinition Load(XmlReader reader, IHighlightingThemeDefinitionReferenceResolver resolver) { return Load(LoadXshd(reader), resolver); } #endregion } } ================================================ FILE: src/HL/Manager/ThemedHighlightingManager.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- #pragma warning disable namespace HL.Manager { using HL.HighlightingTheme; using HL.Interfaces; using HL.Resources; using HL.Xshtd.interfaces; using ICSharpCode.AvalonEdit.Highlighting; using System; using System.Collections.Generic; using System.Collections.ObjectModel; /// /// Implements a Highlighting Manager that associates syntax highlighting definitions with file extentions /// (*.cs -> 'C#') with consideration of the current WPF App theme /// /// Extension App Theme SyntaxHighlighter /// (*.cs + 'Dark') -> 'C#' (with color definitions for 'Dark') /// public class ThemedHighlightingManager : IThemedHighlightingManager { #region fields /// /// Defines the root namespace under which the built-in xshd highlighting /// resource files can be found /// (eg all highlighting for 'Light' should be located here). /// public const string HL_GENERIC_NAMESPACE_ROOT = "HL.Resources.Light"; /// /// Defines the root namespace under which the built-in additional xshtd highlighting theme /// resource files can be found /// (eg 'Dark' and 'TrueBlue' themes should be located here). /// public const string HL_THEMES_NAMESPACE_ROOT = "HL.Resources.Themes"; private readonly object lockObj = new object(); private readonly Dictionary _ThemedHighlightings; #endregion fields #region ctors /// /// Class constructor /// public ThemedHighlightingManager() { _ThemedHighlightings = new Dictionary(); } #endregion ctors #region properties /// /// Gets the current highlighting theme (eg 'Light' or 'Dark') that should be used as /// a base for the syntax highlighting in AvalonEdit. /// public IHLTheme CurrentTheme { get; private set; } /// /// Gets the default HighlightingManager instance. /// The default HighlightingManager comes with built-in highlightings. /// public static IThemedHighlightingManager Instance { get { return DefaultHighlightingManager.Instance; } } #endregion properties #region methods /// /// Gets the highlighting definition by name, or null if it is not found. /// IHighlightingDefinition IHighlightingDefinitionReferenceResolver.GetDefinition(string name) { lock (lockObj) { if (CurrentTheme != null) return CurrentTheme.GetDefinition(name); return null; } } /// /// Gets an (ordered by Name) list copy of all highlightings defined in this object /// or an empty collection if there is no highlighting definition available. /// public ReadOnlyCollection HighlightingDefinitions { get { lock (lockObj) { if (CurrentTheme != null) return CurrentTheme.HighlightingDefinitions; return new ReadOnlyCollection(new List()); } } } /// /// Gets a highlighting definition by extension. /// Returns null if the definition is not found. /// public IHighlightingDefinition GetDefinitionByExtension(string extension) { lock (lockObj) { IHLTheme theme; if (_ThemedHighlightings.TryGetValue(CurrentTheme.Key, out theme) == true) { return theme.GetDefinitionByExtension(extension); } return null; } } /// /// Registers a highlighting definition for the . /// /// The name to register the definition with. /// The file extensions to register the definition for. /// The highlighting definition. public void RegisterHighlighting(string name, string[] extensions, IHighlightingDefinition highlighting) { if (highlighting == null) throw new ArgumentNullException("highlighting"); lock (lockObj) { if (this.CurrentTheme != null) { CurrentTheme.RegisterHighlighting(name, extensions, highlighting); } } } /// /// Registers a highlighting definition. /// /// The name to register the definition with. /// The file extensions to register the definition for. /// A function that loads the highlighting definition. public void RegisterHighlighting(string name, string[] extensions, Func lazyLoadedHighlighting) { if (lazyLoadedHighlighting == null) throw new ArgumentNullException("lazyLoadedHighlighting"); RegisterHighlighting(name, extensions, new DelayLoadedHighlightingDefinition(name, lazyLoadedHighlighting)); } /// /// Sets the current highlighting based on the name of the given highighting theme. /// (eg: WPF APP Theme 'TrueBlue' -> Resolve highlighting 'C#' to 'TrueBlue'->'C#') /// /// Throws an if the WPF APP theme is not known. /// /// public void SetCurrentTheme(string themeNameKey) { SetCurrentThemeInternal(themeNameKey); HLResources.RegisterBuiltInHighlightings(DefaultHighlightingManager.Instance, CurrentTheme); } /// /// Adds another highlighting theme into the current collection of highlighting themes. /// /// /// public void ThemedHighlightingAdd(string key, IHLTheme theme) { lock (lockObj) { _ThemedHighlightings.Add(key, theme); } } /// /// Removes a highlighting theme from the current collection /// of highlighting themes. /// /// public void ThemedHighlightingRemove(string removekey) { lock (lockObj) { _ThemedHighlightings.Remove(removekey); } } /// /// Initializes the current default theme available at start-up of application /// (without registration of highlightings). /// /// protected void SetCurrentThemeInternal(string themeNameKey) { CurrentTheme = _ThemedHighlightings[themeNameKey]; } /// /// Helper method to find the correct namespace of an internal xshd resource /// based on the name of a (WPF) theme (eg. 'TrueBlue') and an internal /// constant (eg. 'HL.Resources') /// /// /// protected virtual string GetPrefix(string themeNameKey) { lock (lockObj) { IHLTheme theme; if (_ThemedHighlightings.TryGetValue(themeNameKey, out theme) == true) { return theme.HLBasePrefix; } } return null; } /// /// Gets the highlighting theme definition by name, or null if there is none to be found. /// /// SyntaxDefinition IHighlightingThemeDefinitionReferenceResolver.GetThemeDefinition(string highlightingName) { lock (lockObj) { if (CurrentTheme != null) return CurrentTheme.GetThemeDefinition(highlightingName); return null; } } /// /// Gets the highlighting theme definition by name of the theme (eg 'Dark2' or 'TrueBlue') /// and the highlighting, or null if there is none to be found. /// /// /// SyntaxDefinition IHighlightingThemeDefinitionReferenceResolver.GetThemeDefinition(string hlThemeName, string highlightingName) { lock (lockObj) { IHLTheme highlighting; this._ThemedHighlightings.TryGetValue(hlThemeName, out highlighting); if (highlighting != null) return highlighting.GetThemeDefinition(hlThemeName); return null; } } #endregion methods } } ================================================ FILE: src/HL/Manager/V2Loader.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- #pragma warning disable namespace HL.Manager { using HL.Resources; using ICSharpCode.AvalonEdit.Highlighting; using ICSharpCode.AvalonEdit.Highlighting.Xshd; using System; using System.Collections.Generic; using System.Diagnostics; using System.Windows; using System.Windows.Media; using System.Xml; using System.Xml.Schema; /// /// Loads .xshd files, version 2.0. /// Version 2.0 files are recognized by the namespace. /// static class V2Loader { public const string Namespace = "http://icsharpcode.net/sharpdevelop/syntaxdefinition/2008"; static XmlSchemaSet schemaSet; static XmlSchemaSet SchemaSet { get { if (schemaSet == null) { schemaSet = HighlightingLoader.LoadSchemaSet(new XmlTextReader( HLResources.OpenStream("HL.Modes", "ModeV2.xsd"))); } return schemaSet; } } public static XshdSyntaxDefinition LoadDefinition(XmlReader reader, bool skipValidation) { reader = HighlightingLoader.GetValidatingReader(reader, true, skipValidation ? null : SchemaSet); reader.Read(); return ParseDefinition(reader); } static XshdSyntaxDefinition ParseDefinition(XmlReader reader) { Debug.Assert(reader.LocalName == "SyntaxDefinition"); XshdSyntaxDefinition def = new XshdSyntaxDefinition(); def.Name = reader.GetAttribute("name"); string extensions = reader.GetAttribute("extensions"); if (extensions != null) def.Extensions.AddRange(extensions.Split(';')); ParseElements(def.Elements, reader); Debug.Assert(reader.NodeType == XmlNodeType.EndElement); Debug.Assert(reader.LocalName == "SyntaxDefinition"); return def; } static void ParseElements(ICollection c, XmlReader reader) { if (reader.IsEmptyElement) return; while (reader.Read() && reader.NodeType != XmlNodeType.EndElement) { Debug.Assert(reader.NodeType == XmlNodeType.Element); if (reader.NamespaceURI != Namespace) { if (!reader.IsEmptyElement) reader.Skip(); continue; } switch (reader.Name) { case "RuleSet": c.Add(ParseRuleSet(reader)); break; case "Property": c.Add(ParseProperty(reader)); break; case "Color": c.Add(ParseNamedColor(reader)); break; case "Keywords": c.Add(ParseKeywords(reader)); break; case "Span": c.Add(ParseSpan(reader)); break; case "Import": c.Add(ParseImport(reader)); break; case "Rule": c.Add(ParseRule(reader)); break; default: throw new NotSupportedException("Unknown element " + reader.Name); } } } static XshdElement ParseProperty(XmlReader reader) { XshdProperty property = new XshdProperty(); SetPosition(property, reader); property.Name = reader.GetAttribute("name"); property.Value = reader.GetAttribute("value"); return property; } static XshdRuleSet ParseRuleSet(XmlReader reader) { XshdRuleSet ruleSet = new XshdRuleSet(); SetPosition(ruleSet, reader); ruleSet.Name = reader.GetAttribute("name"); ruleSet.IgnoreCase = reader.GetBoolAttribute("ignoreCase"); CheckElementName(reader, ruleSet.Name); ParseElements(ruleSet.Elements, reader); return ruleSet; } static XshdRule ParseRule(XmlReader reader) { XshdRule rule = new XshdRule(); SetPosition(rule, reader); rule.ColorReference = ParseColorReference(reader); if (!reader.IsEmptyElement) { reader.Read(); if (reader.NodeType == XmlNodeType.Text) { rule.Regex = reader.ReadContentAsString(); rule.RegexType = XshdRegexType.IgnorePatternWhitespace; } } return rule; } static XshdKeywords ParseKeywords(XmlReader reader) { XshdKeywords keywords = new XshdKeywords(); SetPosition(keywords, reader); keywords.ColorReference = ParseColorReference(reader); reader.Read(); while (reader.NodeType != XmlNodeType.EndElement) { Debug.Assert(reader.NodeType == XmlNodeType.Element); keywords.Words.Add(reader.ReadElementString()); } return keywords; } static XshdImport ParseImport(XmlReader reader) { XshdImport import = new XshdImport(); SetPosition(import, reader); import.RuleSetReference = ParseRuleSetReference(reader); if (!reader.IsEmptyElement) reader.Skip(); return import; } static XshdSpan ParseSpan(XmlReader reader) { XshdSpan span = new XshdSpan(); SetPosition(span, reader); span.BeginRegex = reader.GetAttribute("begin"); span.EndRegex = reader.GetAttribute("end"); span.Multiline = reader.GetBoolAttribute("multiline") ?? false; span.SpanColorReference = ParseColorReference(reader); span.RuleSetReference = ParseRuleSetReference(reader); if (!reader.IsEmptyElement) { reader.Read(); while (reader.NodeType != XmlNodeType.EndElement) { Debug.Assert(reader.NodeType == XmlNodeType.Element); switch (reader.Name) { case "Begin": if (span.BeginRegex != null) throw Error(reader, "Duplicate Begin regex"); span.BeginColorReference = ParseColorReference(reader); span.BeginRegex = reader.ReadElementString(); span.BeginRegexType = XshdRegexType.IgnorePatternWhitespace; break; case "End": if (span.EndRegex != null) throw Error(reader, "Duplicate End regex"); span.EndColorReference = ParseColorReference(reader); span.EndRegex = reader.ReadElementString(); span.EndRegexType = XshdRegexType.IgnorePatternWhitespace; break; case "RuleSet": if (span.RuleSetReference.ReferencedElement != null) throw Error(reader, "Cannot specify both inline RuleSet and RuleSet reference"); span.RuleSetReference = new XshdReference(ParseRuleSet(reader)); reader.Read(); break; default: throw new NotSupportedException("Unknown element " + reader.Name); } } } return span; } static Exception Error(XmlReader reader, string message) { return Error(reader as IXmlLineInfo, message); } static Exception Error(IXmlLineInfo lineInfo, string message) { if (lineInfo != null) return new HighlightingDefinitionInvalidException(HighlightingLoader.FormatExceptionMessage(message, lineInfo.LineNumber, lineInfo.LinePosition)); else return new HighlightingDefinitionInvalidException(message); } /// /// Sets the element's position to the XmlReader's position. /// static void SetPosition(XshdElement element, XmlReader reader) { IXmlLineInfo lineInfo = reader as IXmlLineInfo; if (lineInfo != null) { element.LineNumber = lineInfo.LineNumber; element.ColumnNumber = lineInfo.LinePosition; } } static XshdReference ParseRuleSetReference(XmlReader reader) { string ruleSet = reader.GetAttribute("ruleSet"); if (ruleSet != null) { // '/' is valid in highlighting definition names, so we need the last occurence int pos = ruleSet.LastIndexOf('/'); if (pos >= 0) { return new XshdReference(ruleSet.Substring(0, pos), ruleSet.Substring(pos + 1)); } else { return new XshdReference(null, ruleSet); } } else { return new XshdReference(); } } static void CheckElementName(XmlReader reader, string name) { if (name != null) { if (name.Length == 0) throw Error(reader, "The empty string is not a valid name."); if (name.IndexOf('/') >= 0) throw Error(reader, "Element names must not contain a slash."); } } #region ParseColor static XshdColor ParseNamedColor(XmlReader reader) { XshdColor color = ParseColorAttributes(reader); // check removed: invisible named colors may be useful now that apps can read highlighting data //if (color.Foreground == null && color.FontWeight == null && color.FontStyle == null) // throw Error(reader, "A named color must have at least one element."); color.Name = reader.GetAttribute("name"); CheckElementName(reader, color.Name); color.ExampleText = reader.GetAttribute("exampleText"); return color; } static XshdReference ParseColorReference(XmlReader reader) { string color = reader.GetAttribute("color"); if (color != null) { int pos = color.LastIndexOf('/'); if (pos >= 0) { return new XshdReference(color.Substring(0, pos), color.Substring(pos + 1)); } else { return new XshdReference(null, color); } } else { return new XshdReference(ParseColorAttributes(reader)); } } static XshdColor ParseColorAttributes(XmlReader reader) { XshdColor color = new XshdColor(); SetPosition(color, reader); IXmlLineInfo position = reader as IXmlLineInfo; color.Foreground = ParseColor(position, reader.GetAttribute("foreground")); color.Background = ParseColor(position, reader.GetAttribute("background")); color.FontWeight = ParseFontWeight(reader.GetAttribute("fontWeight")); color.FontStyle = ParseFontStyle(reader.GetAttribute("fontStyle")); color.Underline = reader.GetBoolAttribute("underline"); return color; } internal readonly static ColorConverter ColorConverter = new ColorConverter(); internal readonly static FontWeightConverter FontWeightConverter = new FontWeightConverter(); internal readonly static FontStyleConverter FontStyleConverter = new FontStyleConverter(); static HighlightingBrush ParseColor(IXmlLineInfo lineInfo, string color) { if (string.IsNullOrEmpty(color)) return null; if (color.StartsWith("SystemColors.", StringComparison.Ordinal)) return GetSystemColorBrush(lineInfo, color); else return FixedColorHighlightingBrush((Color?)ColorConverter.ConvertFromInvariantString(color)); } internal static SystemColorHighlightingBrush GetSystemColorBrush(IXmlLineInfo lineInfo, string name) { Debug.Assert(name.StartsWith("SystemColors.", StringComparison.Ordinal)); string shortName = name.Substring(13); var property = typeof(SystemColors).GetProperty(shortName + "Brush"); if (property == null) throw Error(lineInfo, "Cannot find '" + name + "'."); return new SystemColorHighlightingBrush(property); } static HighlightingBrush FixedColorHighlightingBrush(Color? color) { if (color == null) return null; return new SimpleHighlightingBrush(color.Value); } static FontWeight? ParseFontWeight(string fontWeight) { if (string.IsNullOrEmpty(fontWeight)) return null; return (FontWeight?)FontWeightConverter.ConvertFromInvariantString(fontWeight); } static FontStyle? ParseFontStyle(string fontStyle) { if (string.IsNullOrEmpty(fontStyle)) return null; return (FontStyle?)FontStyleConverter.ConvertFromInvariantString(fontStyle); } #endregion } } ================================================ FILE: src/HL/Manager/XmlHighlightingDefinition.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- #pragma warning disable namespace HL.Manager { using HL.HighlightingTheme; using ICSharpCode.AvalonEdit.Highlighting; using ICSharpCode.AvalonEdit.Highlighting.Xshd; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Runtime.Serialization; using System.Text; using System.Text.RegularExpressions; [Serializable] sealed class XmlHighlightingDefinition : IHighlightingDefinition { public string Name { get; private set; } public XmlHighlightingDefinition(XshdSyntaxDefinition xshd, IHighlightingDefinitionReferenceResolver resolver) { InitializeDefinitions(xshd, resolver); } /// /// Class constructor from highlighting theme definition resolver /// and highlighting definition (and resolver) /// /// /// /// public XmlHighlightingDefinition(SyntaxDefinition themedHighlights, XshdSyntaxDefinition xshd, IHighlightingDefinitionReferenceResolver resolver ) { _themedHighlights = themedHighlights; InitializeDefinitions(xshd, resolver); } #region RegisterNamedElements sealed class RegisterNamedElementsVisitor : IXshdVisitor { XmlHighlightingDefinition def; internal readonly Dictionary ruleSets = new Dictionary(); public RegisterNamedElementsVisitor(XmlHighlightingDefinition def) { this.def = def; } public object VisitRuleSet(XshdRuleSet ruleSet) { HighlightingRuleSet hrs = new HighlightingRuleSet(); ruleSets.Add(ruleSet, hrs); if (ruleSet.Name != null) { if (ruleSet.Name.Length == 0) throw Error(ruleSet, "Name must not be the empty string"); if (def.ruleSetDict.ContainsKey(ruleSet.Name)) throw Error(ruleSet, "Duplicate rule set name '" + ruleSet.Name + "'."); def.ruleSetDict.Add(ruleSet.Name, hrs); } ruleSet.AcceptElements(this); return null; } public object VisitColor(XshdColor color) { if (color.Name != null) { if (color.Name.Length == 0) throw Error(color, "Name must not be the empty string"); if (def.colorDict.ContainsKey(color.Name)) throw Error(color, "Duplicate color name '" + color.Name + "'."); def.colorDict.Add(color.Name, new HighlightingColor()); } return null; } public object VisitKeywords(XshdKeywords keywords) { return keywords.ColorReference.AcceptVisitor(this); } public object VisitSpan(XshdSpan span) { span.BeginColorReference.AcceptVisitor(this); span.SpanColorReference.AcceptVisitor(this); span.EndColorReference.AcceptVisitor(this); return span.RuleSetReference.AcceptVisitor(this); } public object VisitImport(XshdImport import) { return import.RuleSetReference.AcceptVisitor(this); } public object VisitRule(XshdRule rule) { return rule.ColorReference.AcceptVisitor(this); } } #endregion #region TranslateElements sealed class TranslateElementVisitor : IXshdVisitor { readonly XmlHighlightingDefinition def; readonly Dictionary ruleSetDict; readonly Dictionary reverseRuleSetDict; readonly IHighlightingDefinitionReferenceResolver resolver; HashSet processingStartedRuleSets = new HashSet(); HashSet processedRuleSets = new HashSet(); bool ignoreCase; public TranslateElementVisitor(XmlHighlightingDefinition def, Dictionary ruleSetDict, IHighlightingDefinitionReferenceResolver resolver) { Debug.Assert(def != null); Debug.Assert(ruleSetDict != null); this.def = def; this.ruleSetDict = ruleSetDict; this.resolver = resolver; reverseRuleSetDict = new Dictionary(); foreach (var pair in ruleSetDict) { reverseRuleSetDict.Add(pair.Value, pair.Key); } } public object VisitRuleSet(XshdRuleSet ruleSet) { HighlightingRuleSet rs = ruleSetDict[ruleSet]; if (processedRuleSets.Contains(ruleSet)) return rs; if (!processingStartedRuleSets.Add(ruleSet)) throw Error(ruleSet, "RuleSet cannot be processed because it contains cyclic "); bool oldIgnoreCase = ignoreCase; if (ruleSet.IgnoreCase != null) ignoreCase = ruleSet.IgnoreCase.Value; rs.Name = ruleSet.Name; foreach (XshdElement element in ruleSet.Elements) { object o = element.AcceptVisitor(this); HighlightingRuleSet elementRuleSet = o as HighlightingRuleSet; if (elementRuleSet != null) { Merge(rs, elementRuleSet); } else { HighlightingSpan span = o as HighlightingSpan; if (span != null) { rs.Spans.Add(span); } else { HighlightingRule elementRule = o as HighlightingRule; if (elementRule != null) { rs.Rules.Add(elementRule); } } } } ignoreCase = oldIgnoreCase; processedRuleSets.Add(ruleSet); return rs; } static void Merge(HighlightingRuleSet target, HighlightingRuleSet source) { target.Rules.AddRange(source.Rules); target.Spans.AddRange(source.Spans); } public object VisitColor(XshdColor color) { HighlightingColor c = null; if (def._themedHighlights == null) { if (color.Name != null) c = def.colorDict[color.Name]; else if (color.Foreground == null && color.Background == null && color.Underline == null && color.FontStyle == null && color.FontWeight == null) return null; else c = new HighlightingColor(); c.Name = color.Name; c.Foreground = color.Foreground; c.Background = color.Background; c.Underline = color.Underline; c.FontStyle = color.FontStyle; c.FontWeight = color.FontWeight; } return c; } public object VisitKeywords(XshdKeywords keywords) { if (keywords.Words.Count == 0) return Error(keywords, "Keyword group must not be empty."); foreach (string keyword in keywords.Words) { if (string.IsNullOrEmpty(keyword)) throw Error(keywords, "Cannot use empty string as keyword"); } StringBuilder keyWordRegex = new StringBuilder(); // We can use "\b" only where the keyword starts/ends with a letter or digit, otherwise we don't // highlight correctly. (example: ILAsm-Mode.xshd with ".maxstack" keyword) if (keywords.Words.All(IsSimpleWord)) { keyWordRegex.Append(@"\b(?>"); // (?> = atomic group // atomic groups increase matching performance, but we // must ensure that the keywords are sorted correctly. // "\b(?>in|int)\b" does not match "int" because the atomic group captures "in". // To solve this, we are sorting the keywords by descending length. int i = 0; foreach (string keyword in keywords.Words.OrderByDescending(w => w.Length)) { if (i++ > 0) keyWordRegex.Append('|'); keyWordRegex.Append(Regex.Escape(keyword)); } keyWordRegex.Append(@")\b"); } else { keyWordRegex.Append('('); int i = 0; foreach (string keyword in keywords.Words) { if (i++ > 0) keyWordRegex.Append('|'); if (char.IsLetterOrDigit(keyword[0])) keyWordRegex.Append(@"\b"); keyWordRegex.Append(Regex.Escape(keyword)); if (char.IsLetterOrDigit(keyword[keyword.Length - 1])) keyWordRegex.Append(@"\b"); } keyWordRegex.Append(')'); } return new HighlightingRule { Color = GetColor(keywords, keywords.ColorReference), Regex = CreateRegex(keywords, keyWordRegex.ToString(), XshdRegexType.Default) }; } static bool IsSimpleWord(string word) { return char.IsLetterOrDigit(word[0]) && char.IsLetterOrDigit(word, word.Length - 1); } Regex CreateRegex(XshdElement position, string regex, XshdRegexType regexType) { if (regex == null) throw Error(position, "Regex missing"); RegexOptions options = RegexOptions.CultureInvariant | RegexOptions.ExplicitCapture; if (regexType == XshdRegexType.IgnorePatternWhitespace) options |= RegexOptions.IgnorePatternWhitespace; if (ignoreCase) options |= RegexOptions.IgnoreCase; try { return new Regex(regex, options); } catch (ArgumentException ex) { throw Error(position, ex.Message); } } HighlightingColor GetColor(XshdElement position, XshdReference colorReference) { if (colorReference.InlineElement != null) { return (HighlightingColor)colorReference.InlineElement.AcceptVisitor(this); } else if (colorReference.ReferencedElement != null) { IHighlightingDefinition definition = GetDefinition(position, colorReference.ReferencedDefinition); HighlightingColor color = definition.GetNamedColor(colorReference.ReferencedElement); if (color == null) throw Error(position, "Could not find color named '" + colorReference.ReferencedElement + "'."); return color; } else { return null; } } IHighlightingDefinition GetDefinition(XshdElement position, string definitionName) { if (definitionName == null) return def; if (resolver == null) throw Error(position, "Resolving references to other syntax definitions is not possible because the IHighlightingDefinitionReferenceResolver is null."); IHighlightingDefinition d = resolver.GetDefinition(definitionName); if (d == null) throw Error(position, "Could not find definition with name '" + definitionName + "'."); return d; } HighlightingRuleSet GetRuleSet(XshdElement position, XshdReference ruleSetReference) { if (ruleSetReference.InlineElement != null) { return (HighlightingRuleSet)ruleSetReference.InlineElement.AcceptVisitor(this); } else if (ruleSetReference.ReferencedElement != null) { IHighlightingDefinition definition = GetDefinition(position, ruleSetReference.ReferencedDefinition); HighlightingRuleSet ruleSet = definition.GetNamedRuleSet(ruleSetReference.ReferencedElement); if (ruleSet == null) throw Error(position, "Could not find rule set named '" + ruleSetReference.ReferencedElement + "'."); return ruleSet; } else { return null; } } public object VisitSpan(XshdSpan span) { string endRegex = span.EndRegex; if (string.IsNullOrEmpty(span.BeginRegex) && string.IsNullOrEmpty(span.EndRegex)) throw Error(span, "Span has no start/end regex."); if (!span.Multiline) { if (endRegex == null) endRegex = "$"; else if (span.EndRegexType == XshdRegexType.IgnorePatternWhitespace) endRegex = "($|" + endRegex + "\n)"; else endRegex = "($|" + endRegex + ")"; } HighlightingColor wholeSpanColor = GetColor(span, span.SpanColorReference); return new HighlightingSpan { StartExpression = CreateRegex(span, span.BeginRegex, span.BeginRegexType), EndExpression = CreateRegex(span, endRegex, span.EndRegexType), RuleSet = GetRuleSet(span, span.RuleSetReference), StartColor = GetColor(span, span.BeginColorReference), SpanColor = wholeSpanColor, EndColor = GetColor(span, span.EndColorReference), SpanColorIncludesStart = true, SpanColorIncludesEnd = true }; } public object VisitImport(XshdImport import) { HighlightingRuleSet hrs = GetRuleSet(import, import.RuleSetReference); XshdRuleSet inputRuleSet; if (reverseRuleSetDict.TryGetValue(hrs, out inputRuleSet)) { // ensure the ruleset is processed before importing its members if (VisitRuleSet(inputRuleSet) != hrs) Debug.Fail("this shouldn't happen"); } return hrs; } public object VisitRule(XshdRule rule) { return new HighlightingRule { Color = GetColor(rule, rule.ColorReference), Regex = CreateRegex(rule, rule.Regex, rule.RegexType) }; } } #endregion static Exception Error(XshdElement element, string message) { if (element.LineNumber > 0) return new HighlightingDefinitionInvalidException( "Error at line " + element.LineNumber + ":\n" + message); else return new HighlightingDefinitionInvalidException(message); } Dictionary ruleSetDict = new Dictionary(); Dictionary colorDict = new Dictionary(); [OptionalField] Dictionary propDict = new Dictionary(); private bool _isThemeInitialized; /// /// Defines highlighting theme information (if any is applicable) for this highlighting. /// private readonly SyntaxDefinition _themedHighlights; public HighlightingRuleSet MainRuleSet { get; private set; } public HighlightingRuleSet GetNamedRuleSet(string name) { ApplyTheme(); if (string.IsNullOrEmpty(name)) return MainRuleSet; HighlightingRuleSet r; if (ruleSetDict.TryGetValue(name, out r)) return r; else return null; } public HighlightingColor GetNamedColor(string name) { ApplyTheme(); HighlightingColor c; if (colorDict.TryGetValue(name, out c)) return c; else return null; } public IEnumerable NamedHighlightingColors { get { ApplyTheme(); return colorDict.Values; } } public override string ToString() { return this.Name; } public IDictionary Properties { get { return propDict; } } private void InitializeDefinitions(XshdSyntaxDefinition xshd, IHighlightingDefinitionReferenceResolver resolver) { this.Name = xshd.Name; // Create HighlightingRuleSet instances var rnev = new RegisterNamedElementsVisitor(this); xshd.AcceptElements(rnev); // Assign MainRuleSet so that references can be resolved foreach (XshdElement element in xshd.Elements) { XshdRuleSet xrs = element as XshdRuleSet; if (xrs != null && xrs.Name == null) { if (MainRuleSet != null) throw Error(element, "Duplicate main RuleSet. There must be only one nameless RuleSet!"); else MainRuleSet = rnev.ruleSets[xrs]; } } if (MainRuleSet == null) throw new HighlightingDefinitionInvalidException("Could not find main RuleSet."); // Translate elements within the rulesets (resolving references and processing imports) xshd.AcceptElements(new TranslateElementVisitor(this, rnev.ruleSets, resolver)); foreach (var p in xshd.Elements.OfType()) propDict.Add(p.Name, p.Value); } private void ApplyTheme() { if (_themedHighlights == null || _isThemeInitialized) return; _isThemeInitialized = true; // Replace matching colors in highlightingdefinition with colors from theme sytaxdefinition. var items = colorDict.ToArray(); for (int i = 0; i < items.Length; i++) { HighlightingColor newColor = _themedHighlights.ColorGet(items[i].Key); if (newColor != null) { string key = items[i].Key; colorDict.Remove(key); colorDict.Add(key, newColor); } } } } } ================================================ FILE: src/HL/Manager/XshtdLoader.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- #pragma warning disable namespace HL.Manager { using HL.Resources; using HL.Xshtd; using ICSharpCode.AvalonEdit.Highlighting; using System; using System.Collections.Generic; using System.Diagnostics; using System.Windows; using System.Windows.Media; using System.Xml; using System.Xml.Schema; /// /// Loads .xshd files, version 2.0. /// Version 2.0 files are recognized by the namespace. /// static class XshtdLoader { public const string Namespace = "http://icsharpcode.net/sharpdevelop/themesyntaxdefinition/2019"; static XmlSchemaSet schemaSet; static XmlSchemaSet SchemaSet { get { if (schemaSet == null) { schemaSet = HighlightingLoader.LoadSchemaSet(new XmlTextReader( HLResources.OpenStream("HL.Modes", "ModeV2_htd.xsd"))); } return schemaSet; } } public static XhstdThemeDefinition LoadDefinition(XmlReader reader, bool skipValidation) { reader = HighlightingLoader.GetValidatingReader(reader, true, skipValidation ? null : SchemaSet); reader.Read(); return ParseDefinition(reader); } static XhstdThemeDefinition ParseDefinition(XmlReader reader) { Debug.Assert(reader.LocalName == "ThemeSyntaxDefinition"); XhstdThemeDefinition def = new XhstdThemeDefinition(); def.Name = reader.GetAttribute("name"); Stack xmlPath = new Stack(); xmlPath.Push(def); ParseElements(def.Elements, reader, xmlPath); var def1 = xmlPath.Pop(); Debug.Assert(object.Equals(def, def1)); Debug.Assert(reader.NodeType == XmlNodeType.EndElement); Debug.Assert(reader.LocalName == "ThemeSyntaxDefinition"); return def; } static void ParseElements(ICollection c, XmlReader reader, Stack xmlPath) { if (reader.IsEmptyElement) return; while (reader.Read() && reader.NodeType != XmlNodeType.EndElement) { Debug.Assert(reader.NodeType == XmlNodeType.Element); if (reader.NamespaceURI != Namespace) { if (!reader.IsEmptyElement) reader.Skip(); continue; } switch (reader.Name) { case "SyntaxDefinition": c.Add(ParseSyntaxDefinition(reader, xmlPath)); break; case "Color": var parent = xmlPath.Peek() as XshtdSyntaxDefinition; if (parent == null) throw new Exception("Syntax Error: Color cannot occurr outside of SyntaxDefinition"); c.Add(ParseNamedColor(reader, parent)); break; case "GlobalStyles": ParseGlobalStyles(reader, xmlPath); break; case "DefaultStyle": case "CurrentLineBackground": case "LineNumbersForeground": case "Selection": case "NonPrintableCharacter": case "Hyperlink": ParseGlobalStyle(reader, xmlPath); break; default: throw new NotSupportedException("Unknown element " + reader.Name); } } } static XshtdSyntaxDefinition ParseSyntaxDefinition(XmlReader reader, Stack xmlPath) { Debug.Assert(reader.LocalName == "SyntaxDefinition"); XshtdSyntaxDefinition def = new XshtdSyntaxDefinition(); def.Name = reader.GetAttribute("name"); string extensions = reader.GetAttribute("extensions"); if (extensions != null) def.Extensions.AddRange(extensions.Split(';')); xmlPath.Push(def); ParseElements(def.Elements, reader, xmlPath); def = xmlPath.Pop() as XshtdSyntaxDefinition; Debug.Assert(def != null); Debug.Assert(reader.NodeType == XmlNodeType.EndElement); Debug.Assert(reader.LocalName == "SyntaxDefinition"); return def; } private static XshtdElement ParseGlobalStyles(XmlReader reader, Stack xmlPath) { Debug.Assert(reader.LocalName == "GlobalStyles"); var def = xmlPath.Peek() as XhstdThemeDefinition; Debug.Assert(def != null); xmlPath.Push(def.GlobalStyleElements); ParseElements(null, reader, xmlPath); var def2 = xmlPath.Pop(); Debug.Assert(object.Equals(def.GlobalStyleElements, def2)); Debug.Assert(reader.NodeType == XmlNodeType.EndElement); Debug.Assert(reader.LocalName == "GlobalStyles"); return null; } private static XshtdElement ParseGlobalStyle(XmlReader reader, Stack xmlPath) { var def = xmlPath.Peek() as XshtdGlobalStyles; Debug.Assert(def != null); var style = new XshtdGlobalStyle(def); style.TypeName = reader.Name; string color; color = reader.GetAttribute("background"); if (string.IsNullOrEmpty(color) == false) style.background = (Color?)ColorConverter.ConvertFromInvariantString(color); color = reader.GetAttribute("foreground"); if (string.IsNullOrEmpty(color) == false) style.foreground = (Color?)ColorConverter.ConvertFromInvariantString(color); color = reader.GetAttribute("bordercolor"); if (string.IsNullOrEmpty(color) == false) style.bordercolor = (Color?)ColorConverter.ConvertFromInvariantString(color); def.Elements.Add(style); return def; } static Exception Error(XmlReader reader, string message) { return Error(reader as IXmlLineInfo, message); } static Exception Error(IXmlLineInfo lineInfo, string message) { if (lineInfo != null) return new HighlightingDefinitionInvalidException(HighlightingLoader.FormatExceptionMessage(message, lineInfo.LineNumber, lineInfo.LinePosition)); else return new HighlightingDefinitionInvalidException(message); } /// /// Sets the element's position to the XmlReader's position. /// static void SetPosition(XshtdElement element, XmlReader reader) { IXmlLineInfo lineInfo = reader as IXmlLineInfo; if (lineInfo != null) { element.LineNumber = lineInfo.LineNumber; element.ColumnNumber = lineInfo.LinePosition; } } static void CheckElementName(XmlReader reader, string name) { if (name != null) { if (name.Length == 0) throw Error(reader, "The empty string is not a valid name."); if (name.IndexOf('/') >= 0) throw Error(reader, "Element names must not contain a slash."); } } #region ParseColor static XshtdColor ParseNamedColor(XmlReader reader, XshtdSyntaxDefinition syntax) { XshtdColor color = ParseColorAttributes(reader, syntax); // check removed: invisible named colors may be useful now that apps can read highlighting data //if (color.Foreground == null && color.FontWeight == null && color.FontStyle == null) // throw Error(reader, "A named color must have at least one element."); color.Name = reader.GetAttribute("name"); CheckElementName(reader, color.Name); color.ExampleText = reader.GetAttribute("exampleText"); return color; } static XshtdColor ParseColorAttributes(XmlReader reader, XshtdSyntaxDefinition syntax) { XshtdColor color = new XshtdColor(syntax); SetPosition(color, reader); IXmlLineInfo position = reader as IXmlLineInfo; color.Foreground = ParseColor(position, reader.GetAttribute("foreground")); color.Background = ParseColor(position, reader.GetAttribute("background")); color.FontWeight = ParseFontWeight(reader.GetAttribute("fontWeight")); color.FontStyle = ParseFontStyle(reader.GetAttribute("fontStyle")); color.Underline = reader.GetBoolAttribute("underline"); return color; } internal readonly static ColorConverter ColorConverter = new ColorConverter(); internal readonly static FontWeightConverter FontWeightConverter = new FontWeightConverter(); internal readonly static FontStyleConverter FontStyleConverter = new FontStyleConverter(); static HighlightingBrush ParseColor(IXmlLineInfo lineInfo, string color) { if (string.IsNullOrEmpty(color)) return null; if (color.StartsWith("SystemColors.", StringComparison.Ordinal)) return GetSystemColorBrush(lineInfo, color); else return FixedColorHighlightingBrush((Color?)ColorConverter.ConvertFromInvariantString(color)); } internal static SystemColorHighlightingBrush GetSystemColorBrush(IXmlLineInfo lineInfo, string name) { Debug.Assert(name.StartsWith("SystemColors.", StringComparison.Ordinal)); string shortName = name.Substring(13); var property = typeof(SystemColors).GetProperty(shortName + "Brush"); if (property == null) throw Error(lineInfo, "Cannot find '" + name + "'."); return new SystemColorHighlightingBrush(property); } static HighlightingBrush FixedColorHighlightingBrush(Color? color) { if (color == null) return null; return new SimpleHighlightingBrush(color.Value); } static FontWeight? ParseFontWeight(string fontWeight) { if (string.IsNullOrEmpty(fontWeight)) return null; return (FontWeight?)FontWeightConverter.ConvertFromInvariantString(fontWeight); } static FontStyle? ParseFontStyle(string fontStyle) { if (string.IsNullOrEmpty(fontStyle)) return null; return (FontStyle?)FontStyleConverter.ConvertFromInvariantString(fontStyle); } #endregion } } ================================================ FILE: src/HL/Modes/ModeV1.xsd ================================================ This schema defines the syntax for mode definitions in SharpDevelop. The schema can be simplified quite a bit but it does the job as is. If you are using this file as a reference it is probably easiest to scroll to the botton to find the definition of the root element called SyntaxDefinition and then unwind the different type definitions and refernces. Note on coloring: Many tags define how some symbol should be colored. If a specific symbol can not be matched onto either a Span definition, Keyword, or a Digit/Number it will be rendered in the current default color. Which is the default color of the current span or the default color of the mode as a whole if no span has been entered. ================================================ FILE: src/HL/Modes/ModeV2.xsd ================================================ ================================================ FILE: src/HL/Modes/ModeV2_htd.xsd ================================================ ================================================ FILE: src/HL/Resources/HLResources.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- #pragma warning disable namespace HL.Resources { using System.IO; using HL.Manager; internal class HLResources { /// /// Open a object to an internal resource (eg: xshd file) /// to load its contents from an 'Embedded Resource'. /// /// /// /// public static Stream OpenStream(string prefix, string name) { string fileRef = prefix + "." + name; Stream s = typeof(HLResources).Assembly.GetManifestResourceStream(fileRef); if (s == null) throw new FileNotFoundException("The resource file '" + fileRef + "' was not found."); return s; } /// /// Registers the built-in highlighting definitions on first time request for a definition /// or when the application changes its WPF Theme (eg. from 'Light' to 'Dark') to load the /// appropriate highlighting resource when queried for it. /// /// /// internal static void RegisterBuiltInHighlightings( DefaultHighlightingManager hlm, IHLTheme theme) { // This registration was already performed for this highlighting theme if (theme.IsBuiltInThemesRegistered == true) return; hlm.RegisterHighlighting(theme, "XmlDoc", null, "XmlDoc.xshd"); hlm.RegisterHighlighting(theme, "C#", new[] { ".cs" }, "CSharp-Mode.xshd"); hlm.RegisterHighlighting(theme, "Gcode", new[] { ".nc" }, "Gcode.xshd"); hlm.RegisterHighlighting(theme, "GRazor", new[] { ".grazor" }, "GRazor-Mode.xshd"); hlm.RegisterHighlighting(theme, "JavaScript", new[] { ".js" }, "JavaScript-Mode.xshd"); hlm.RegisterHighlighting(theme, "HTML", new[] { ".htm", ".html" }, "HTML-Mode.xshd"); hlm.RegisterHighlighting(theme, "ASP/XHTML", new[] { ".asp", ".aspx", ".asax", ".asmx", ".ascx", ".master" }, "ASPX.xshd"); hlm.RegisterHighlighting(theme, "Boo", new[] { ".boo" }, "Boo.xshd"); hlm.RegisterHighlighting(theme, "Coco", new[] { ".atg" }, "Coco-Mode.xshd"); hlm.RegisterHighlighting(theme, "CSS", new[] { ".css" }, "CSS-Mode.xshd"); hlm.RegisterHighlighting(theme, "C++", new[] { ".c", ".h", ".cc", ".cpp", ".hpp" }, "CPP-Mode.xshd"); hlm.RegisterHighlighting(theme, "Java", new[] { ".java" }, "Java-Mode.xshd"); hlm.RegisterHighlighting(theme, "Patch", new[] { ".patch", ".diff" }, "Patch-Mode.xshd"); hlm.RegisterHighlighting(theme, "PowerShell", new[] { ".ps1", ".psm1", ".psd1" }, "PowerShell.xshd"); hlm.RegisterHighlighting(theme, "PHP", new[] { ".php" }, "PHP-Mode.xshd"); hlm.RegisterHighlighting(theme, "Python", new[] { ".py", ".pyw" }, "Python-Mode.xshd"); hlm.RegisterHighlighting(theme, "TeX", new[] { ".tex" }, "Tex-Mode.xshd"); hlm.RegisterHighlighting(theme, "TSQL", new[] { ".sql" }, "TSQL-Mode.xshd"); hlm.RegisterHighlighting(theme, "VB", new[] { ".vb" }, "VB-Mode.xshd"); hlm.RegisterHighlighting(theme, "XML", (".xml;.xsl;.xslt;.xsd;.manifest;.config;.addin;" + ".xshd;.wxs;.wxi;.wxl;.proj;.csproj;.vbproj;.ilproj;" + ".booproj;.build;.xfrm;.targets;.xaml;.xpt;" + ".xft;.map;.wsdl;.disco;.ps1xml;.nuspec").Split(';'), "XML-Mode.xshd"); hlm.RegisterHighlighting(theme, "MarkDown", new[] { ".md" }, "MarkDown-Mode.xshd"); // Additional Highlightings hlm.RegisterHighlighting(theme, "ActionScript3", new[] { ".as" }, "AS3.xshd"); hlm.RegisterHighlighting(theme, "BAT", new[] { ".bat", ".dos" }, "DOSBATCH.xshd"); hlm.RegisterHighlighting(theme, "F#", new[] { ".fs" }, "FSharp-Mode.xshd"); hlm.RegisterHighlighting(theme, "HLSL", new[] { ".fx" }, "HLSL.xshd"); hlm.RegisterHighlighting(theme, "INI", new[] { ".cfg", ".conf", ".ini", ".iss" }, "INI.xshd"); hlm.RegisterHighlighting(theme, "LOG", new[] { ".log" }, "Log.xshd"); hlm.RegisterHighlighting(theme, "Pascal", new[] { ".pas" }, "Pascal.xshd"); hlm.RegisterHighlighting(theme, "PLSQL", new[] { ".plsql" }, "PLSQL.xshd"); hlm.RegisterHighlighting(theme, "Ruby", new[] { ".rb" }, "Ruby.xshd"); hlm.RegisterHighlighting(theme, "Scheme", new[] { ".sls", ".sps", ".ss", ".scm" }, "scheme.xshd"); hlm.RegisterHighlighting(theme, "Squirrel", new[] { ".nut" }, "squirrel.xshd"); hlm.RegisterHighlighting(theme, "TXT", new[] { ".txt" }, "TXT.xshd"); hlm.RegisterHighlighting(theme, "VTL", new[] { ".vtl", ".vm" }, "vtl.xshd"); theme.IsBuiltInThemesRegistered = true; } } } ================================================ FILE: src/HL/Resources/Light/AS3.xshd ================================================ TODO FIXME HACK UNDONE /// // /\* \*/ " " null Infinity NaN undefined true false dynamic private public static intrinsic internal native override protected AS3 final void arguments Array Boolean Class int Math Namespace Number Object RegExp uint XML Bitmap BitmapData DisplayObject DisplayObjectContainer MovieClip Shape Sprite Stage ColorTransform Matrix Point Rectangle Transform Sound Video TextField ContextMenu Keyboard Mouse ByteArray Dictionary Endian Proxy Timer class extends implements import interface new case do while else if for in switch throw get set function var try catch finally while with default break continue delete return each const namespace package include use is as instanceof typeof void \b [\d\w_]+ # an identifier (?=\s*\() # followed by ( \b0[xX][0-9a-fA-F]+ # hex number | \b ( \d+(\.[0-9]+)? #number with optional floating point | \.[0-9]+ #or just starting with floating point ) ([eE][+-]?[0-9]+)? # optional exponent ================================================ FILE: src/HL/Resources/Light/ASPX.xshd ================================================ <% %> ================================================ FILE: src/HL/Resources/Light/Boo.xshd ================================================  TODO FIXME HACK UNDONE """ """ \# // /\* \*/ " " \$\{ } ' ' @/ / /\S+/ self super is isa and or not else elif if match case unless otherwise for in while break continue return yield goto try raise ensure except retry success fixed unsafe bool double single byte sbyte short ushort int uint long ulong date timespan decimal char object duck string regex void cast as override static virtual abstract final transient partial public protected private internal namespace import from get set null value true false ast using unchecked checked lock getter required rawArrayIndexing normalArrayIndexing yieldAll assert array matrix print gets prompt enumerate zip filter map cat __eval__ __switch__ constructor destructor def include event ref pass enum class struct interface mixin callable do of [\d\w_]+(?=(\s*\()) \b0[xX][0-9a-fA-F]+|(\b\d+(\.[0-9]+)?|\.[0-9]+)([eE][+-]?[0-9]+)? /\* \*/ /\* \*/ ================================================ FILE: src/HL/Resources/Light/CPP-Mode.xshd ================================================ [?,.;()\[\]{}+\-/%*<>^=~!&]+ __abstract __box __delegate __gc __identifier __nogc __pin __property __sealed __try_cast __typeof __value __event __hook __raise __unhook __interface ref class ref struct value class value struct interface class interface struct enum class enum struct delegate event property abstract override sealed generic where finally for each gcnew in initonly literal nullptr this and and_eq bitand bitor new not not_eq or or_eq xor xor_eq using namespace friend private protected public const volatile static bool char unsigned union virtual double float short signed void class enum struct false true do for while break continue goto return catch throw try case else if switch default asm auto compl mutable const_cast delete dynamic_cast explicit export extern inline int long operator register reinterpret_cast sizeof static_cast template typedef typeid typename \# // /\* \*/ " " ' ' [\d\w_]+(?=(\s*\()) \b0[xX][0-9a-fA-F]+|(\b\d+(\.[0-9]+)?|\.[0-9]+)([eE][+-]?[0-9]+)? ================================================ FILE: src/HL/Resources/Light/CSS-Mode.xshd ================================================  /\* \*/ \{ \} \# \s [\d\w] /\* \*/ \: \;|(?=\}) " " ' ' ================================================ FILE: src/HL/Resources/Light/CSharp-Mode.xshd ================================================ TODO FIXME HACK UNDONE \# (define|undef|if|elif|else|endif|line)\b // (region|endregion|error|warning|pragma)\b ///(?!/) // /\* \*/ " " ' ' @" " \$" " @[\w\d_]+ this base as is new sizeof typeof stackalloc true false else if switch case default do for foreach in while lock break continue goto return yield partial global where select group by into from ascending descending orderby let join on equals var dynamic await try throw catch finally checked unchecked fixed unsafe bool byte char decimal double enum float int long sbyte short struct uint ushort ulong class interface delegate object string void explicit implicit operator params ref out abstract const event extern override readonly sealed static virtual volatile async public protected private internal namespace using get set add remove null value nameof \b [\d\w_]+ # an identifier (?=\s*\() # followed by ( \b0[xX][0-9a-fA-F]+ # hex number | ( \b\d+(\.[0-9]+)? #number with optional floating point | \.[0-9]+ #or just starting with floating point ) ([eE][+-]?[0-9]+)? # optional exponent [?,.;()\[\]{}+\-/%*<>^+~!|&]+ ================================================ FILE: src/HL/Resources/Light/Coco-Mode.xshd ================================================ [{}\(\)\[\]|+\-=\.]+ ANY CHARACTERS COMMENTS COMPILER CONTEXT END FROM IF IGNORE NAMESPACE NESTED PRAGMAS PRODUCTIONS SYNC TO TOKENS TOKENNAMES WEAK using // /\* \*/ COMPILER TOKENNAMES " " ' ' < > \(\. \.\) \b0[xX][0-9a-fA-F]+|(\b\d+(\.[0-9]+)?|\.[0-9]+)([eE][+-]?[0-9]+)? \b0[xX][0-9a-fA-F]+|(\b\d+(\.[0-9]+)?|\.[0-9]+)([eE][+-]?[0-9]+)? \b0[xX][0-9a-fA-F]+|(\b\d+(\.[0-9]+)?|\.[0-9]+)([eE][+-]?[0-9]+)? \b0[xX][0-9a-fA-F]+|(\b\d+(\.[0-9]+)?|\.[0-9]+)([eE][+-]?[0-9]+)? ================================================ FILE: src/HL/Resources/Light/DOSBATCH.xshd ================================================  %[0-9] %[A-Z]+% [-/][A-Z]+ %[0-9] %[A-Z]+% [?,;()\[\]{}+\-/%*<>^+~!|&]+ [G][O][T][O]+[ ]+[A-Z]+ ^:[A-Z]+ % % [ ?,.;()\[\]{}+\-/%*<>^+~!|&]+[0-9]+[ ?,.;()\[\]{}+\-/%*<>^+~!|&]+\n ^@[A-Z]+ (ECHO\.) ASSOC AT ATTRIB BREAK CACLS CALL CD CHCP CHDIR CHKDSK CLS CMD COLOR COMP COMPACT CONVERT COPY DATE DEL DIR DISKCOMP DISKCOPY DOSKEY ECHO ENABLEEXTENSIONS ENDLOCAL ERASE EXIT FC FIND FINDSTR FOR FORMAT FTYPE GRAFTABL HELP IF KEYB LABEL MD MKDIR MODE MORE MOVE NET PATH PAUSE POPD PRINT PROMPT PUSHD RD RECOVER REN RENAME REPLACE RESTORE RMDIR SET SETLOCAL SHIFT SORT START SUBST TIME TITLE TREE TYPE VER VERIFY VOL XCOPY DO IN NOT ERRORLEVEL EXIST EQU NEQ LSS LEQ GTR GEQ CMDEXTVERSION DEFINED CON COM MIN MAX SEPARATE SHARED LOW NORMAL HIGH REALTIME WAIT OTHER nul EOL SKIP DELIMS TOKENS ON OFF USE == EQU NEQ LSS LEQ GTR GEQ ================================================ FILE: src/HL/Resources/Light/FSharp-Mode.xshd ================================================ TODO FIXME HACK UNDONE \# (define|undef|if|elif|else|endif|line)\b // (region|endregion|error|warning|pragma)\b /// // \(\* \*\) " " ' ' @" " @[\w\d_]+ and as assert begin default do done downcast downto else enum exception extern false finally for fun function if in inherit land lazy let match module mutable new of open or rec sig struct then to true try type val when inline upcast while atomic break checked component const constraint constructor continue decimal eager event external fixed functor include method mixin process property pure readonly return sealed class end interface delegate object string abstract member with override static virtual volatile async public protected private internal namespace using get set add remove null \b [\d\w_]+ # an identifier (?=\s*\() # followed by ( \b0[xX][0-9a-fA-F]+ # hex number | ( \b\d+(\.[0-9]+)? #number with optional floating point | \.[0-9]+ #or just starting with floating point ) ([eE][+-]?[0-9]+)? # optional exponent [?,.;()\[\]{}+\-/%*<>^+~!|&]+ ================================================ FILE: src/HL/Resources/Light/GRazor-Mode.xshd ================================================  \@\* \*\@ \@\{ \} \@\( \) \@functions\s*\{ \} \@for \} \@if \} \@foreach \} \@while \} @@ \@ \)|\< (?<=@for)\s*\( \) @: $ (?<=@foreach)\s*\( \) @: $ (?<=@if)\s*\( \) @: $ (?<=@while)\s*\( \) @: $ . & [\w\d\#]+ ; & [\w\d\#]* #missing ; @@ \@\* \*\@ @ \{ \} \( \) " " ' ' this base as is new sizeof typeof stackalloc true false else if switch case default do for foreach in while lock break continue goto return yield partial global where select group by into from ascending descending orderby let join on equals var dynamic try throw catch finally checked unchecked fixed unsafe bool byte char decimal double enum float int long sbyte short struct uint ushort ulong class interface delegate object string void explicit implicit operator params ref out abstract const event extern override readonly sealed static virtual volatile public protected private internal namespace using get set add remove null value \b [\d\w_]+ # an identifier (?=\s*\() # followed by ( \b0[xX][0-9a-fA-F]+ # hex number | ( \b\d+(\.[0-9]+)? #number with optional floating point | \.[0-9]+ #or just starting with floating point ) ([eE][+-]?[0-9]+)? # optional exponent [?,.;()\[\]{}+\-/%*<>^+~!|&]+ \{ \} \( \) \{ \} \( \) ================================================ FILE: src/HL/Resources/Light/Gcode.xshd ================================================  N([0-9.-]) (?![0-9.-]) N G([0-9.-]) (?![0-9.-]) G X([0-9.-]) (?![0-9.-]) X Y([0-9.-]) (?![0-9.-]) Y Z([0-9.-]) (?![0-9.-]) Z M([0-9.-]) (?![0-9.-]) M S([0-9.-]) (?![0-9.-]) S I([0-9.-]) (?![0-9.-]) I J([0-9.-]) (?![0-9.-]) J K([0-9.-]) (?![0-9.-]) K %([0-9.-]) (?![0-9.-]) % ================================================ FILE: src/HL/Resources/Light/HLSL.xshd ================================================ [?,.;:()\[\]{}+\-/%*<>^!|]+ (if |else |break |continue |do |for |switch |while |return |technique |pass |compile |sampler |register |typedef |struct |auto|catch|char|class|const_cast |default|delete|dynamic_cast |enum|explicit|friend|goto |long|mutable|new|operator |private|protected|public |reinterpret_cast|short|sizeof|static_cast |template|this|throw|try|typename|union |using|virtual|void|extern)(\s|[;{(]) (Buffer|bool|int|uint|half|float|double)([1-4]?)(x[1-4])? (?=[(]|\s|\r|\n) (Texture) (?=[(]|\s|\r|\n) (sampler1D|sampler2D|sampler3D|samplerCUBE|sampler_state|SamplerState) (?i)(?<=\W)(VertexShader|PixelShader|GeometryShader| AddressU|AddressV|AddressW|BorderColor|Filter|MaxAnisotropy| MaxLOD|MinLOD|MipLODBias|ComparisonFunc|ComparisonFilter| MipFilter|MinFilter|MagFilter|Texture|MaxLOD|MinLOD |AlphaBlendEnable|AlphaFunc|AlphaRef|AlphaTestEnable|BlendOp |ColorWriteEnable|DepthBias|DestBlend|DitherEnable|FillMode |LastPixel|ShadeMode|SlopeScaleDepthBias|SrcBlend |StencilEnable|StencilFail|StencilFunc|StencilMask |StencilPass|StencilRef|StencilWriteMask|StencilZFail |TextureFactor|ZEnable|ZFunc |Ambient|AmbientMaterialSource|Clipping|ClipPlaneEnable |ColorVertex|CullMode|DiffuseMaterialSource|EmissiveMaterialSource |FogColor|FogDensity|FogEnable|FogEnd|FogStart|FogTableMode|FogVertexMode |IndexedVertexBlendEnable|Lighting|LocalViewer|MultiSampleAntialias|MultiSampleMask |NormalizeNormals|PatchSegments|PointScale_A|PointScale_B|PointScale_C |PointScaleEnable|PointSize|PointSize_Min|PointSize_Max|PointSpriteEnable |RangeFogEnable|SpecularEnable|SpecularMaterialSource|TweenFactor|VertexBlend)(?=\s*[=]) (?i)(?<=\W)(Wrap\d(\d)?) (?i)(?<=([=]\s*))(true|false|wrap|mirror|clamp|border|mirroronce |none|point|linear|anisotropic|pyramidalquad|gaussianquad|convolutionmono |zero|one|srccolor|invsrccolor|srcalpha|invsrcalpha|destalpha|invdestalpha |destcolor|invdestcolor|srcalphasat|bothsrcalpha|bothinvsrcalpha |blendfactor|invblendfactor|srccolor2|invsrccolor2 |never|less|equal|lessequal|greater|notequal|greaterequal|always|wireframe|solid |flat|gouraud|phong |keep|replace|incrsat|decrsat|invert|decr|twosided|cw|ccw|exp|exp2|linear |disable|1weights|2weights|3weights|tweening|0weights)(?=\s|[;{(]) (ps|vs)_\d_\d(?=\s|[;{(]) (?<=([:]\s*)) (BINORMAL|BLENDINDICES|BLENDWEIGHT|COLOR|NORMAL|POSITION| PSIZE|TANGENT|TEXCOORD|TESSFACTOR|DEPTH|SV_ClipDistance| SV_CullDistance|SV_Target) (\d?) ([:]\s*)(POSITIONT |FOG |PSIZE |VFACE |VPOS |SV_Coverage |SV_Depth |SV_DispatchThreadID |SV_GroupID |SV_GroupIndex |SV_GroupThreadID |SV_InsideTessFactor |SV_IsFrontFace |SV_OutputControlPointID |SV_Position |SV_RenderTargetArrayIndex |SV_SampleIndex |SV_TessFactor |SV_ViewportArrayIndex |SV_InstanceID |SV_PrimitiveID |SV_VertexID) (abs |acos |all |AllMemoryBarrier |AllMemoryBarrierWithGroupSync |any |asdouble |asfloat |asin |asint |asuint |atan |atan2 |ceil |clamp |clip |cos |cosh |countbits |cross |D3DCOLORtoUBYTE4 |ddx |ddx_coarse |ddx_fine |ddy |ddy_coarse |ddy_fine |degrees |determinant |DeviceMemoryBarrier |DeviceMemoryBarrierWithGroupSync |distance |dot |dst |EvaluateAttributeAtCentroid |EvaluateAttributeAtSample |EvaluateAttributeSnapped |exp |exp2 |f16tof32 |f32tof16 |facetoforward |firstbithigh |firstbitlow |floor |fmod |frac |frexp |fwidth |GetRenderTargetSampleCount |GetRenderTargetSamplePosition |GroupMamoryBarrier |GroupMamoryBarrierWithGroupSync |InterlockedAdd |InterlockedCompareExchange |InterlockedCompareStore |InterlockedExchange |InterlockedMax |InterlockedMin |InterlockedOr |InterlockedXor |isfinite |isinf |isnan |ldexp |lerp |lit |log |log10 |log2 |mad |max |min |modf |mul |noise |normalize |pow |Process2DQuadTessFactorsAvg |Process2DQuadTessFactorsMax |Process2DQuadTessFactorsMin |ProcessIsolineTessFactors |ProcessQuadTessFactorsAvg |ProcessQuadTessFactorsMax |ProcessQuadTessFactorsMin |ProcessTriTessFactorsAvg |ProcessTriTessFactorsMax |ProcessTriTessFactorsMin |radians |rcp |reflect |refract |reversebits |round |rsqrt |saturate |sign |sin |sincos |sinh |smoothstep |sqrt |step |tan |tanh |tex1D |tex1Dbias |tex1Dgrad |tex1Dlod |tex1Dproj |tex2D |tex2Dbias |tex2Dgrad |tex2Dlod |tex3D |tex3Dbias |tex3Dgrad |tex3Dlod |tex3Dproj |texCUBE |texCUBEbias |texCUBEgrad |texCUBElod |texCUBEproj |transpose |trunc)(\s*[(]) [\d\w_]+(?=(\s*\()) \b0[xX][0-9a-fA-F]+|(\b\d+(\.[0-9]+)?|\.[0-9]+)([eE][+-]?[0-9]+)? ================================================ FILE: src/HL/Resources/Light/HTML-Mode.xshd ================================================ <!-- --> <script\ lang="JavaScript"> </script> <script\s.*?text/javascript.*?> </script> <script\ lang="JScript"> </script> <script\ lang="VBScript"> </script> <script> </script> <script[^\w\d_] </script> < > & ; \b0[xX][0-9a-fA-F]+|(\b\d+(\.[0-9]+)?|\.[0-9]+)([eE][+-]?[0-9]+)? \b0[xX][0-9a-fA-F]+|(\b\d+(\.[0-9]+)?|\.[0-9]+)([eE][+-]?[0-9]+)? aacute agrave acirc amp atilde aring auml aelig ccedil copy eacute egrave ecirc euml iacute igrave icirc iuml eth gt lt nbsp ntilde oacute ograve ocirc otilde ouml oslash quot reg szlig uacute ugrave ucirc uuml yacute thorn trade yuml \b0[xX][0-9a-fA-F]+|(\b\d+(\.[0-9]+)?|\.[0-9]+)([eE][+-]?[0-9]+)? / = !DOCTYPE A ABBR ACRONYM ADDRESS APPLET AREA B BASE BASEFONT BGSOUND BDO BIG BLINK BLOCKQUOTE BODY BR BUTTON CAPTION CENTER CITE CODE COL COLGROUP COMMENT DD DEL DFN DIR DIV DL DT EM EMBED FIELDSET FONT FORM FRAME FRAMESET H H1 H2 H3 H4 H5 H6 HEAD HR HTA:APPLICATION HTML I IFRAME IMG INPUT INS ISINDEX KBD LABEL LEGEnd LI LINK LISTING MAP MARQUEE MENU META MULTICOL NEXTID NOBR NOFRAMES NOSCRIPT OBJECT OL OPTGROUP OPTION P PARAM PLAINTEXT PRE Q S SAMP SCRIPT SELECT SERVER SMALL SOUND SPACER Span STRONG STYLE SUB SUP TABLE TBODY TD TEXTAREA TEXTFLOW TFOOT TH THEAD TITLE TR TT U VAR WBR XMP abbr accept-charset accept accesskey action align alink alt applicationname archive axis background behavior bgcolor bgproperties border bordercolor bordercolordark bordercolorligh borderstyle caption cellpadding cellspacing char charoff charset checked cite class classid clear code codetype color cols colspan compact content coords data datetime declare defer dir direction disabled dynsrc enctype face for frame frameborder framespacing gutter headers height href hreflang hspace http-equiv icon id ismap label language leftmargin link longdesc loop lowsrc marginheight marginwidth maximizebutton maxlength media method methods minimizebutton multiple name nohref noresize noshade nowrap object onabort onblur onchange onclick ondblclick onerror onfocus onkeydown onkeypress onkeyup onload onmousedown onmousemove onmouseout onmouseover onmouseup onreset onselect onsubmit onunload profile prompt readonly rel rev rows rowspan rules runat scheme scope scrollamount scrolldelay scrolling selected shape showintaskbar singleinstance size span src standby start style summary sysmenu tabindex target text title topmargin type urn usemap valign value valuetype version vlink vrml vspace width windowstate wrap " " ' ' [\d\w_]+(?=(\s*=)) \b0[xX][0-9a-fA-F]+|(\b\d+(\.[0-9]+)?|\.[0-9]+)([eE][+-]?[0-9]+)? ================================================ FILE: src/HL/Resources/Light/INI.xshd ================================================ ' ' " " ; \# \[ \] ^[0-9A-Z\-]+ = [?,.;()\[\]{}+\-/%*<>^+~!|&]+ [?,.;()\[\]{}+\-/%*<>^+~!|&]+[0-9]+[ ?,.;()\[\]{}+\-/%*<>^+~!|&]+\n ================================================ FILE: src/HL/Resources/Light/Java-Mode.xshd ================================================ [?,.()\[\]{}+\-/%*<>^!|]+ this super new instanceof true false else if switch case do for while break continue default goto return try throw catch finally boolean double int short long float byte char class interface object void abstract const static final native extends implements volatile transient throws strictfp synchronized public protected private package import null // /\* \*/ " " ' ' [\d\w_]+(?=(\s*\()) \b0[xX][0-9a-fA-F]+|(\b\d+(\.[0-9]+)?|\.[0-9]+)([eE][+-]?[0-9]+)? TODO @author @version @param @return @exception @throws @see @since @serial @serialField @serialData @deprecated \b0[xX][0-9a-fA-F]+|(\b\d+(\.[0-9]+)?|\.[0-9]+)([eE][+-]?[0-9]+)? ================================================ FILE: src/HL/Resources/Light/JavaScript-Mode.xshd ================================================ break continue delete else for function if in new return this typeof var void while with abstract boolean byte case catch char class const debugger default do double enum export extends final finally float goto implements import instanceof int interface long native package private protected public short static super switch synchronized throw throws transient try volatile Array Boolean Date Function Global Math Number Object RegExp String false null true NaN Infinity eval parseInt parseFloat escape unescape isNaN isFinite // /\* \*/ / / " " ' ' \b0[xX][0-9a-fA-F]+|(\b\d+(\.[0-9]+)?|\.[0-9]+)([eE][+-]?[0-9]+)? ================================================ FILE: src/HL/Resources/Light/Log.xshd ================================================ Info Information Trace Debug Error Warn Warning Exception Fatal ' ' " " ; \# \[ \] [?,.;()\[\]{}+\-/%*<>^+~!|&]+ [?,.;()\[\]{}+\-/%*<>^+~!|&]+[0-9]+[ ?,.;()\[\]{}+\-/%*<>^+~!|&]+\n [0-9][0-9][0-9][0-9]\-[0-9][0-9]\-[0-9][0-9] [0-9][0-9]\:[0-9][0-9]\:[0-9][0-9]\.[0-9][0-9][0-9] [0-9][0-9]\:[0-9][0-9]\:[0-9][0-9] ================================================ FILE: src/HL/Resources/Light/MarkDown-Mode.xshd ================================================  ^\#.* \*\*.*\*\* __.*__ \*(?![ ]).*\* _.*_ `.*` ^\t ^(?!\t) ^[ ]{4} ^(?![ ]{4}) ^> ^(?!>) \!\[.*\]\[.*\] \[.*\]\(.*\) \[.*\]\[.*\] [ ]{2}$ ================================================ FILE: src/HL/Resources/Light/PHP-Mode.xshd ================================================ \# // /\* \*/ \b0[xX][0-9a-fA-F]+ # hex number | \b0[0-9]+ # octal number | ( \b\d+(\.[0-9]+)? #number with optional floating point | \.[0-9]+ #or just starting with floating point ) ([eE][+-]?[0-9]+)? # optional exponent [?,.:;()\[\]{}+\-/%*<>&^!|~@]+ \b [\d\w_]+ # an identifier (?=\s*\() # followed by ( ' ' " " <<<\"?[\d\w_]+\"?$ ^[\d\w_]+; <<<\'[\d\w_]+\'$ ^[\d\w_]+; global my var and or new clone instanceof xor true false else else switch case endif elseif do for foreach while endwhile exit break continue default goto return require include require include function int integer real double float string array object class void public private ================================================ FILE: src/HL/Resources/Light/PLSQL.xshd ================================================  -- /\* \*/ ' ' " " all alter and any array arrow as asc at begin between by case check clusters cluster colauth columns compress connect crash create current decimal declare default delete desc distinct drop else end exception exclusive exists exec fetch form for from goto grant group having identified if in indexes index insert intersect into is like lock minus mode nocompress not nowait null of on option or order overlaps prior procedure public range record resource revoke select share size sql start subtype tabauth table then to type union unique update use values view views when where with a add agent aggregate array attribute authid avg bfile_base binary blob_base block body both bound bulk byte c call calling cascade char char_base character charsetform charsetid charset clob_base close collect comment commit committed compiled constant constructor context convert count cursor customdatum dangling data date date_base day define deterministic double duration element elsif empty escape except exceptions execute exit external final fixed float forall force function general hash heap hidden hour immediate including indicator indices infinite instantiable int interface interval invalidate isolation java language large leading length level library like2 like4 likec limit limited local long loop map max maxlen member merge min minute mod modify month multiset name nan national native nchar new nocopy number_base object ocicoll ocidatetime ocidate ociduration ociinterval ociloblocator ocinumber ociraw ocirefcursor ociref ocirowid ocistring ocitype only opaque open operator oracle oradata organization orlany orlvary others out overriding package parallel_enable parameter parameters partition pascal pipe pipelined pragma precision private raise range raw read record ref reference rem remainder rename result return returning reverse rollback row sample save savepoint sb1 sb2 sb4 second segment self separate sequence serializable set short size_t some sparse sqlcode sqldata sqlname sqlstate standard static stddev stored string struct style submultiset subpartition substitutable subtype sum synonym tdo the time timestamp timezone_abbr timezone_hour timezone_minute timezone_region trailing transac transactional trusted type ub1 ub2 ub4 under unsigned untrusted use using valist value variable variance varray varying void while work wrapped write year zone abs greatest sin acos group_id sinh add_months hextoraw soundex ascii initcap sqlcode asciistr instr sqlerrm asin lag sqrt atan last_day stddev atan2 lead substr avg least sum bfilename length sys_context bin_to_num lnnvl sysdate bitand ln systimestamp cardinality localtimestamp tan case statement log tanh cast lower to_char ceil lpad to_clob chartorowid ltrim to_date chr max to_dsinterval coalesce median to_lob compose min to_multi_byte concat mod to_nclob concat with months_between to_number convert nanvl to_single_byte corr new_time to_timestamp cos next_day to_timestamp_tz cosh nullif to_yminterval count numtodsinterval translate covar_pop numtoyminterval trim covar_samp nvl trunc (dates) cume_dist nvl2 trunc (numbers) current_date power tz_offset current_timestamp rank uid dbtimezone rawtohex upper decode remainder user decompose replace userenv dense_rank round (dates) var_pop dump round (numbers) var_samp exp rpad variance extract rtrim vsize floor sessiontimezone from_tz sign ================================================ FILE: src/HL/Resources/Light/Pascal.xshd ================================================ TODO FIXME HACK UNDONE @param @returns [?,.;()\[\]{}+\-/%*<>^+~!|&\#]+ // { } " " ' ' integer byte real boolean char shortint word longint string and not or in div mod array const downto file forward label main nil packed record repeat set to type until var begin case do else for function goto if procedure program then of end while with abs arctan chr cos dispose eof eoln exp false get input ln maxint new odd ord output page pred put read readln reset rewrite round sin sqr sqrt succ text true trunc write writeln [\d\w_]+(?=(\s*\()) \b0[xX][0-9a-fA-F]+|(\b\d+(\.[0-9]+)?|\.[0-9]+)([eE][+-]?[0-9]+)? ================================================ FILE: src/HL/Resources/Light/Patch-Mode.xshd ================================================  Index:\s == --- \+\+\+ @@ - \+ \s ================================================ FILE: src/HL/Resources/Light/PowerShell.xshd ================================================  \# <\# \#> " " ' ' @" "@ while param end define else from foreach var dynamicparam filter dp until for exit switch process begin elseif if in data class using function catch finally throw trap try break continue return class -not -band -bor -replace -ireplace -creplace -and -or -is -isnot -as -lt -le -gt -ge -eq -ne -contains -notcontains -like -notlike -match -notmatch \$[\d\w_]+ [\w]+-[\w]+ \b0[xX][0-9a-fA-F]+ # hex number | ( \b\d+(\.[0-9]+)? #number with optional floating point | \.[0-9]+ #or just starting with floating point ) ([eE][+-]?[0-9]+)? # optional exponent [?,.;()\[\]{}+\-/%*<>^+~!|&]+ ================================================ FILE: src/HL/Resources/Light/Python-Mode.xshd ================================================ TODO FIXME HACK UNDONE \# ''' ''' """ """ " " ' ' and as assert break class continue def del elif else except exec False finally for from global if import in is lambda None nonlocal not or pass print raise return True try while with yield async await \b [\d\w_]+ # an identifier (?=\s*\() # followed by ( \b0[xX][0-9a-fA-F]+ # hex number ( \b\d+(\.[0-9]+)? #number with optional floating point | \.[0-9]+ #or just starting with floating point ) ([eE][+-]?[0-9]+)? # optional exponent ================================================ FILE: src/HL/Resources/Light/Ruby.xshd ================================================ TODO FIXME HACK UNDONE \b0[xX][0-9a-fA-F]+|(\b\d+(\.[0-9]+)?|\.[0-9]+)([eE][+-]?[0-9]+)? [?,.:;()\[\]{}+\-/%*<>^=~!]+ ' ' """ """ \=begin \=end \# " " abort Array at_exit autoload binding callcc caller chomp chop eval exec exit fail Float fork format gets global_variables gsub Integer lambda proc load local_variables loop open p print print printf putc puts rand readline scan select set_trace_func sleep split sprintf srand String syscall system sub test throw trace_var trap untrace_var class module public protected private begin rescue ensure raise catch def end undef for do in while until break yield redo return retry next and not or nil elsif else if then case unless true false defined self super import alias include require [\d\w_]+(?=(\s*\()) @([\w]+) &([\w]+) TODO FIXME HACK UNDONE =begin =end TODO FIXME HACK UNDONE =begin =end ================================================ FILE: src/HL/Resources/Light/TSQL-Mode.xshd ================================================ TODO FIXME HACK UNDONE -- /\* \*/ ' ' abs absolute access acos add add_months adddate admin after aggregate all allocate alter and any app_name are array as asc ascii asin assertion at atan atn2 audit authid authorization autonomous_transaction avg before begin benchmark between bfilename bigint bin binary binary_checksum binary_integer bit bit_count bit_and bit_or blob body boolean both breadth bulk by call cascade cascaded case cast catalog ceil ceiling char char_base character charindex chartorowid check checksum checksum_agg chr class clob close cluster coalesce col_length col_name collate collation collect column comment commit completion compress concat concat_ws connect connection constant constraint constraints constructorcreate contains containsable continue conv convert corr corresponding cos cot count count_big covar_pop covar_samp create cross cube cume_dist current current_date current_path current_role current_time current_timestamp current_user currval cursor cycle data datalength databasepropertyex date date_add date_format date_sub dateadd datediff datename datepart datetime day db_id db_name deallocate dec declare decimal decode default deferrable deferred degrees delete dense_rank depth deref desc describe descriptor destroy destructor deterministic diagnostics dictionary disconnect difference distinct do domain double drop dump dynamic each else elsif empth encode encrypt end end-exec equals escape every except exception exclusive exec execute exists exit exp export_set extends external extract false fetch first first_value file float floor file_id file_name filegroup_id filegroup_name filegroupproperty fileproperty for forall foreign format formatmessage found freetexttable from from_days fulltextcatalog fulltextservice function general get get_lock getdate getansinull getutcdate global go goto grant greatest group grouping having heap hex hextoraw host host_id host_name hour ident_incr ident_seed ident_current identified identity if ifnull ignore immediate in increment index index_col indexproperty indicator initcap initial initialize initially inner inout input insert instr instrb int integer interface intersect interval into is is_member is_srvrolemember is_null is_numeric isdate isnull isolation iterate java join key lag language large last last_day last_value lateral lcase lead leading least left len length lengthb less level like limit limited ln lpad local localtime localtimestamp locator lock log log10 long loop lower ltrim make_ref map match max maxextents mid min minus minute mlslabel mod mode modifies modify module month months_between names national natural naturaln nchar nclob new new_time newid next next_day nextval no noaudit nocompress nocopy nolock none not nowait null nullif number number_base numeric nvl nvl2 object object_id object_name object_property ocirowid oct of off offline old on online only opaque open operator operation option or ord order ordinalityorganization others out outer output package pad parameter parameters partial partition path pctfree percent_rank pi pls_integer positive positiven postfix pow power pragma precision prefix preorder prepare preserve primary prior private privileges procedure public radians raise rand range rank ratio_to_export raw rawtohex read reads real record recursive ref references referencing reftohex relative release release_lock rename repeat replace resource restrict result return returns reverse revoke right rollback rollup round routine row row_number rowid rowidtochar rowlabel rowlock rownum rows rowtype rpad rtrim savepoint schema scroll scope search second section seddev_samp select separate sequence session session_user set sets share sign sin sinh size smallint some soundex space specific specifictype sql sqlcode sqlerrm sqlexception sqlstate sqlwarning sqrt start state statement static std stddev stdev_pop strcmp structure subdate substr substrb substring substring_index subtype successful sum synonym sys_context sys_guid sysdate system_user table tan tanh temporary terminate than then time timestamp timezone_abbr timezone_minute timezone_hour timezone_region tinyint to top to_char to_date to_days to_number to_single_byte trailing transaction translate translation treat trigger trim true trunc truncate type ucase uid under union unique unknown unnest update upper usage use user userenv using validate value values var_pop var_samp varbinary varchar varchar2 variable variance varying view vsize when whenever where with without while work write year zone ================================================ FILE: src/HL/Resources/Light/TXT.xshd ================================================  /\* \*/ BUG FIX BUG BUGS HACK TODO TODOS DONE TICK [?,.;()\[\]{}+\-/%*<>^+~!|&]+ [ ?,.;()\[\]{}+\-/%*<>^+~!|&]+[0-9]+[ ?,.;()\[\]{}+\-/%*<>^+~!|&]+\n ================================================ FILE: src/HL/Resources/Light/Tex-Mode.xshd ================================================ TODO FIXME HACK UNDONE Bug Problem \d \$ \$ \\\( \\\) \\\[ \\\] \[ \] [^\\] (&)|(\\\ )|(\\\\)|(\\@)|(\\\$)|(\\&)|(\\%)|(\\\#)|(\\{)|(\\})|(\\/) (\\[\w]+) ({[\w]+.*}) (%)$ % ({)|(}) % ) ) { } [ ] = ! + - / * > < & | ^ ~ . , ; ? : ' ` ================================================ FILE: src/HL/Resources/Light/VB-Mode.xshd ================================================ " " (?<=(^\s*))\# (?<!(^\s*))\# \# ''' ' \bREM\b Boolean Byte Char Date Decimal Double Integer Long Object SByte Short Single String UInteger ULong UShort Variant AddressOf And AndAlso Await Is IsNot Like Mod New Not Or OrElse Xor False Me MyBase MyClass Nothing True CBool CByte CChar CDate CDbl CDec CInt CLng CObj CSByte CShort CSng CStr CType CUInt CULng CUShort DirectCast GetType GetXmlNamespace IIf TryCast TypeOf AddHandler Alias As ByRef ByVal Call Case Catch Class Const Continue Declare Default Delegate Dim Do Each Else ElseIf End EndIf Enum Erase Error Event Exit Finally For Friend Function Get Global GoSub GoTo Handles If Implements Imports In Inherits Interface Let Lib Loop Module MustInherit MustOverride Namespace Narrowing New Next NotInheritable NotOverridable Of On Operator Option Optional Overloads Overridable Overrides ParamArray Partial Private Property Protected Public RaiseEvent ReadOnly ReDim RemoveHandler Resume Return Select Set Shadows Shared Static Step Stop Structure Sub SyncLock Then Throw To Try Using Wend When While Widening With WithEvents WriteOnly Aggregate Ansi Ascending Async Auto Binary By Compare Custom Descending Distinct Equals Explicit From Group Infer Into Iterator Join Key Off Preserve Skip Strict Take Text Unicode Until Where Yield Const Else ElseIf End ExternalChecksum ExternalSource If Region ================================================ FILE: src/HL/Resources/Light/XML-Mode.xshd ================================================ <!-- --> <!\[CDATA\[ ]]> <!DOCTYPE > <\? \?> < > " "|(?=<) ' '|(?=<) [\d\w_\-\.]+(?=(\s*=)) = & [\w\d\#]+ ; & [\w\d\#]* #missing ; ================================================ FILE: src/HL/Resources/Light/XmlDoc.xshd ================================================ < > " " / | = c code example exception list para param paramref permission remarks returns see seealso summary value type name cref item term description listheader typeparam typeparamref ================================================ FILE: src/HL/Resources/Light/scheme.xshd ================================================ ; \#\| \|\# import export library define set! lambda begin if cond let letrec else map cons car null value \b0[xX][0-9a-fA-F]+ # hex number | ( \b\d+(\.[0-9]+)? #number with optional floating point | \.[0-9]+ #or just starting with floating point ) ([eE][+-]?[0-9]+)? # optional exponent [?,.;()\[\]{}+\-/%*<>^+~!|&]+ ================================================ FILE: src/HL/Resources/Light/squirrel.xshd ================================================ TODO FIXME HACK UNDONE \# /// // /\* \*/ " " @" " [?,.;()\[\]{}+\-/%*<>^+~!|&]+ GGen_Point GGen_Path GGen_Amplitudes GGen_Data_2D GGen_Data_1D else if switch case default for while break local catch clone continue const delegate delete else enum extends for function null resume return switch this throw typeof parent yield constructor vargc vargv instanceof true false static \b [\d\w_]+ # an identifier (?=\s*\() # followed by ( \b0[xX][0-9a-fA-F]+ # hex number | \b ( \d+(\.[0-9]+)? #number with optional floating point | \.[0-9]+ #or just starting with floating point ) ([eE][+-]?[0-9]+)? # optional exponent ================================================ FILE: src/HL/Resources/Light/vtl.xshd ================================================ ' ' " " \#\# \#\* \*\# \# [\w\d]+ \$([\d\w]+)([.])([\d\w]+) \$([\d\w]+)([.])([\d\w]+) ([.])([\d\w]+) \$([\d\w]+) [?,;()\[\]{}+\-/%*<>^+~!|&]+ [?,.;()\[\]{}+\-/%*<>^+~!|&]+[0-9]+[ ?,.;()\[\]{}+\-/%*<>^+~!|&]+\n ================================================ FILE: src/HL/Resources/Themes/Dark.xshtd ================================================  ================================================ FILE: src/HL/Resources/Themes/TrueBlue.xshtd ================================================  ================================================ FILE: src/HL/Resources/Themes/VS2019_Dark.xshtd ================================================  ================================================ FILE: src/HL/Xshtd/IXshtdVisitor.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - © Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- #pragma warning disable // Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team // // Permission is hereby granted, free of charge, to any person obtaining a copy of this // software and associated documentation files (the "Software"), to deal in the Software // without restriction, including without limitation the rights to use, copy, modify, merge, // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons // to whom the Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all copies or // substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE // FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. namespace HL.Xshtd { /// /// Implements an interface for usage in a Visitor pattern based implementation. /// This visitor pattern can be used to visit the elements of an XSHTD element tree. /// /// A visitor pattern can be used in many ways, here its used for syntax checks and /// object conversion (from POCO XML object to non-xml .net object). /// public interface IXshtdVisitor { /// /// Implements the visitor for a named color ( object) /// that is contained in a object. /// /// /// /// object VisitColor(XshtdSyntaxDefinition syntax, XshtdColor color); /// /// Implements the visitor for the object. /// /// the element to be visited. /// object VisitSyntaxDefinition(XshtdSyntaxDefinition syntax); /// /// Implements the visitor for the object. /// /// the element to be visited. /// object VisitGlobalStyles(XshtdGlobalStyles globStyles); /// /// Implements the visitor for the object /// contained in a object. /// /// /// /// object VisitGlobalStyle(XshtdGlobalStyles globStyles, XshtdGlobalStyle style); } } ================================================ FILE: src/HL/Xshtd/XhstdThemeDefinition.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - © Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- #pragma warning disable // Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team // // Permission is hereby granted, free of charge, to any person obtaining a copy of this // software and associated documentation files (the "Software"), to deal in the Software // without restriction, including without limitation the rights to use, copy, modify, merge, // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons // to whom the Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all copies or // substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE // FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. namespace HL.Xshtd { using System; using System.Collections.Generic; using ICSharpCode.AvalonEdit.Utils; /// /// An Xml highlighting theme element. /// /// for equivalent run-time object. /// [Serializable] public class XhstdThemeDefinition : XshtdElement { /// /// Creates a new XhstdThemeDefinition object. /// public XhstdThemeDefinition() { this.Elements = new NullSafeCollection(); this.GlobalStyleElements = new XshtdGlobalStyles(); } /// /// Gets/sets the highlighting theme definition name (eg. 'Dark', 'TrueBlue') /// as stated in the Name attribute of the xshtd (xs highlighting theme definition) file. /// public string Name { get; set; } /// /// Gets the collection of elements. /// public IList Elements { get; private set; } /// /// Gets the collection of elements. /// public XshtdGlobalStyles GlobalStyleElements { get; private set; } /// /// Applies the visitor to all elements. /// public override object AcceptVisitor(IXshtdVisitor visitor) { foreach (XshtdElement element in Elements) { element.AcceptVisitor(visitor); } // Visit Global Styles foreach (XshtdElement element in GlobalStyleElements.Elements) { element.AcceptVisitor(visitor); } return null; } } } ================================================ FILE: src/HL/Xshtd/XmlHighlightingThemeDefinition.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- #pragma warning disable namespace HL.Xshtd { using HL.HighlightingTheme; using HL.Xshtd.interfaces; using ICSharpCode.AvalonEdit.Highlighting; using System.Collections.Generic; using System.Diagnostics; /// /// Implements a highlighting theme definition object that provides all run-time /// relevant properties and methods to work with themes in the context of highlightings. /// /// for equivalent Xml persistance layer object. /// internal class XmlHighlightingThemeDefinition : IHighlightingThemeDefinition { #region fields private Dictionary syntaxDefDict; private Dictionary _GlobalStyles; private readonly XhstdThemeDefinition _xshtd; #endregion fields #region ctors /// /// Class constructor /// public XmlHighlightingThemeDefinition(XhstdThemeDefinition xshtd, IHighlightingThemeDefinitionReferenceResolver resolver) : this() { // Create HighlightingRuleSet instances xshtd.AcceptVisitor(new RegisterNamedElementsVisitor(this)); // Translate elements within the rulesets (resolving references and processing imports) xshtd.AcceptVisitor(new TranslateElementVisitor(this, resolver)); _xshtd = xshtd; } /// /// Class constructor /// protected XmlHighlightingThemeDefinition() { syntaxDefDict = new Dictionary(); _GlobalStyles = new Dictionary(); } #endregion ctors #region properties /// /// Gets/sets the highlighting theme definition name (eg. 'Dark', 'TrueBlue') /// as stated in the Name attribute of the xshtd (xs highlighting theme definition) file. /// public string Name { get { return _xshtd.Name; } } /// /// Gets all global stayles in the collection of global styles. /// public IEnumerable GlobalStyles { get { return _GlobalStyles.Values; } } #endregion properties #region methods /// /// Gets the syntaxdefinition colors that should be applied for a certain highlighting (eg 'C#') /// within this theme (eg TrueBlue). /// /// /// public SyntaxDefinition GetNamedSyntaxDefinition(string name) { SyntaxDefinition item = null; syntaxDefDict.TryGetValue(name, out item); return item; } /// /// Gets a highlighting color based on the name of the syntax definition /// and the name of the color that should be contained in it. /// /// /// /// public HighlightingColor GetNamedColor(string synDefName, string colorName) { var synDef = GetNamedSyntaxDefinition(synDefName); if (synDef == null) return null; return synDef.ColorGet(colorName); } /// /// Gets an enumeration of all highlighting colors that are defined /// for this highlighting pattern (eg. C#) as part of a highlighting theme (eg 'True Blue'). /// public IEnumerable NamedHighlightingColors(string synDefName) { var synDef = GetNamedSyntaxDefinition(synDefName); if (synDef == null) return new List(); return synDef.NamedHighlightingColors; } /// /// Helper method to generate a /// containing more insights (line number, coloumn) to verify the actual problem. /// /// /// /// private static System.Exception Error(XshtdElement element, string message) { if (element.LineNumber > 0) return new HighlightingDefinitionInvalidException( "Error at line " + element.LineNumber + ":\n" + message); else return new HighlightingDefinitionInvalidException(message); } #endregion methods #region private classes /// /// Implements the visitor pattern based on the interface /// to register all elements of a given XML element tree and check whether their syntax /// is as expected or not. /// sealed class RegisterNamedElementsVisitor : IXshtdVisitor { #region fields private readonly XmlHighlightingThemeDefinition def; #endregion fields #region ctors /// /// Class constructor /// public RegisterNamedElementsVisitor(XmlHighlightingThemeDefinition def) : this() { this.def = def; } /// /// Class constructor /// private RegisterNamedElementsVisitor() { } #endregion ctors #region methods /// /// Implements the visitor for the object. /// /// /// public object VisitSyntaxDefinition(XshtdSyntaxDefinition syntax) { if (syntax.Name != null) { if (syntax.Name.Length == 0) throw Error(syntax, "Name must not be the empty string"); if (def.syntaxDefDict.ContainsKey(syntax.Name)) throw Error(syntax, "Duplicate syntax definition name '" + syntax.Name + "'."); def.syntaxDefDict.Add(syntax.Name, new SyntaxDefinition()); } syntax.AcceptElements(this); return null; } /// /// Implements the visitor for a named color ( object) /// that is contained in a object. /// /// Method checks if given color name is unique and adds the color into the internal /// collection of inique colors if it is. /// /// /// /// Always returns null. Throws a /// if color name is a duplicate. public object VisitColor(XshtdSyntaxDefinition syntax, XshtdColor color) { if (color.Name != null) { if (color.Name.Length == 0) throw Error(color, "Name must not be the empty string"); if (syntax == null) throw Error(syntax, "Syntax Definition for theme must not be null"); SyntaxDefinition synDef; if (def.syntaxDefDict.TryGetValue(syntax.Name, out synDef) == false) throw Error(syntax, "Themed Syntax Definition does not exist '" + syntax.Name + "'."); if (synDef.ColorGet(color.Name) == null) synDef.ColorAdd(new HighlightingColor() { Name = color.Name }); else throw Error(color, "Duplicate color name '" + color.Name + "'."); } return null; } /// /// Implements the visitor for the object. /// /// the element to be visited. /// public object VisitGlobalStyles(XshtdGlobalStyles globStyles) { globStyles.AcceptElements(this); return null; } public object VisitGlobalStyle(XshtdGlobalStyles globStyles, XshtdGlobalStyle style) { if (style.TypeName != null) { if (style.TypeName.Length == 0) throw Error(style, "Name must not be the empty string"); if (globStyles == null) throw Error(globStyles, "GlobalStyles parameter must not be null"); GlobalStyle globDef; if (def._GlobalStyles.TryGetValue(style.TypeName, out globDef) == true) throw Error(style, "GlobalStyle definition '" + style.TypeName + "' has duplicates."); globDef = new GlobalStyle(style.TypeName); globDef.backgroundcolor = style.background; globDef.foregroundcolor = style.foreground; globDef.bordercolor = style.bordercolor; globDef.Freeze(); def._GlobalStyles.Add(style.TypeName, new GlobalStyle(style.TypeName)); } return null; } #endregion methods } /// /// Implements the visitor pattern based on the interface /// to convert the content of a object into a /// object. /// sealed class TranslateElementVisitor : IXshtdVisitor { #region fields readonly XmlHighlightingThemeDefinition def; #endregion fields #region ctors /// /// Class constructor. /// /// /// public TranslateElementVisitor(XmlHighlightingThemeDefinition def, IHighlightingThemeDefinitionReferenceResolver resolver) { Debug.Assert(def != null); Debug.Assert(resolver != null); this.def = def; } #endregion ctors #region methods /// /// Implements the visitor for the object. /// /// /// public object VisitSyntaxDefinition(XshtdSyntaxDefinition syntax) { SyntaxDefinition c; if (syntax.Name != null) c = def.syntaxDefDict[syntax.Name]; else { if (syntax.Extensions == null) return null; else c = new SyntaxDefinition(syntax.Name); } // Copy extensions to highlighting theme object foreach (var item in syntax.Extensions) c.Extensions.Add(item); syntax.AcceptElements(this); return c; } /// /// Implements the visitor for a named color ( object) /// that is contained in a object. /// /// /// /// public object VisitColor(XshtdSyntaxDefinition syntax, XshtdColor color) { if (color.Name == null) throw Error(color, "Name must not be null"); if (color.Name.Length == 0) throw Error(color, "Name must not be the empty string"); if (syntax == null) throw Error(syntax, "Syntax Definition for theme must not be null"); SyntaxDefinition synDef; HighlightingColor highColor; if (def.syntaxDefDict.TryGetValue(syntax.Name, out synDef) == false) throw Error(syntax, "Themed Syntax Definition does not exist '" + syntax.Name + "'."); highColor = synDef.ColorGet(color.Name); if (highColor == null) { highColor = new HighlightingColor() { Name = color.Name }; synDef.ColorAdd(highColor); } highColor.Foreground = color.Foreground; highColor.Background = color.Background; highColor.Underline = color.Underline; highColor.FontStyle = color.FontStyle; highColor.FontWeight = color.FontWeight; return highColor; } /// /// Implements the visitor for the object. /// /// the element to be visited. /// public object VisitGlobalStyles(XshtdGlobalStyles globStyles) { globStyles.AcceptElements(this); return null; } public object VisitGlobalStyle(XshtdGlobalStyles globStyles, XshtdGlobalStyle style) { if (style.TypeName == null) throw Error(style, "Name must not be null"); if (style.TypeName.Length == 0) throw Error(style, "Name must not be the empty string"); if (globStyles == null) throw Error(globStyles, "GlobalStyles parameter must not be null"); GlobalStyle globDef; if (def._GlobalStyles.TryGetValue(style.TypeName, out globDef) == false) throw Error(style, "Style definition '" + style.TypeName + "' does not exist in collection of GlobalStyles."); globDef.backgroundcolor = style.background; globDef.foregroundcolor = style.foreground; globDef.bordercolor = style.bordercolor; globDef.Freeze(); return globDef; } #endregion methods } #endregion private classes } } ================================================ FILE: src/HL/Xshtd/XshtdColor.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - © Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- #pragma warning disable // Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team // // Permission is hereby granted, free of charge, to any person obtaining a copy of this // software and associated documentation files (the "Software"), to deal in the Software // without restriction, including without limitation the rights to use, copy, modify, merge, // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons // to whom the Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all copies or // substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE // FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. namespace HL.Xshtd { using ICSharpCode.AvalonEdit.Highlighting; using System; using System.Runtime.Serialization; using System.Security.Permissions; using System.Windows; /// /// A color in an Xshd file. /// [Serializable] public class XshtdColor : XshtdElement, ISerializable { #region fields private readonly XshtdSyntaxDefinition _syntax; #endregion fields #region ctors /// /// Creates a new XshdColor instance that is part of a . /// public XshtdColor(XshtdSyntaxDefinition syntax) { _syntax = syntax; } /// /// Deserializes an XshdColor. /// protected XshtdColor(SerializationInfo info, StreamingContext context) { if (info == null) throw new ArgumentNullException("info"); this.Name = info.GetString("Name"); this.Foreground = (HighlightingBrush)info.GetValue("Foreground", typeof(HighlightingBrush)); this.Background = (HighlightingBrush)info.GetValue("Background", typeof(HighlightingBrush)); if (info.GetBoolean("HasWeight")) this.FontWeight = System.Windows.FontWeight.FromOpenTypeWeight(info.GetInt32("Weight")); if (info.GetBoolean("HasStyle")) this.FontStyle = (FontStyle?)new FontStyleConverter().ConvertFromInvariantString(info.GetString("Style")); this.ExampleText = info.GetString("ExampleText"); if (info.GetBoolean("HasUnderline")) this.Underline = info.GetBoolean("Underline"); } #endregion ctors #region properties /// /// Gets/sets the name. /// public string Name { get; set; } /// /// Gets/sets the foreground brush. /// public HighlightingBrush Foreground { get; set; } /// /// Gets/sets the background brush. /// public HighlightingBrush Background { get; set; } /// /// Gets/sets the font weight. /// public FontWeight? FontWeight { get; set; } /// /// Gets/sets the underline flag /// public bool? Underline { get; set; } /// /// Gets/sets the font style. /// public FontStyle? FontStyle { get; set; } /// /// Gets/Sets the example text that demonstrates where the color is used. /// public string ExampleText { get; set; } #endregion properties /// /// Serializes this XshdColor instance. /// #if DOTNET4 [System.Security.SecurityCritical] #else [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)] #endif public virtual void GetObjectData(SerializationInfo info, StreamingContext context) { if (info == null) throw new ArgumentNullException("info"); info.AddValue("Name", this.Name); info.AddValue("Foreground", this.Foreground); info.AddValue("Background", this.Background); info.AddValue("HasUnderline", this.Underline.HasValue); if (this.Underline.HasValue) info.AddValue("Underline", this.Underline.Value); info.AddValue("HasWeight", this.FontWeight.HasValue); if (this.FontWeight.HasValue) info.AddValue("Weight", this.FontWeight.Value.ToOpenTypeWeight()); info.AddValue("HasStyle", this.FontStyle.HasValue); if (this.FontStyle.HasValue) info.AddValue("Style", this.FontStyle.Value.ToString()); info.AddValue("ExampleText", this.ExampleText); } /// /// Applies the visitor to this element. /// /// /// public override object AcceptVisitor(IXshtdVisitor visitor) { return visitor.VisitColor(_syntax, this); } } } ================================================ FILE: src/HL/Xshtd/XshtdElement.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - © Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- #pragma warning disable // Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team // // Permission is hereby granted, free of charge, to any person obtaining a copy of this // software and associated documentation files (the "Software"), to deal in the Software // without restriction, including without limitation the rights to use, copy, modify, merge, // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons // to whom the Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all copies or // substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE // FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. namespace HL.Xshtd { using System; /// /// An element in a XSHD rule set. /// [Serializable] public abstract class XshtdElement { /// /// Gets the line number in the .xshd file. /// public int LineNumber { get; set; } /// /// Gets the column number in the .xshd file. /// public int ColumnNumber { get; set; } /// /// Applies the visitor to this element. /// public abstract object AcceptVisitor(IXshtdVisitor visitor); } } ================================================ FILE: src/HL/Xshtd/XshtdGlobalStyle.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - © Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- #pragma warning disable namespace HL.Xshtd { using System; using System.Windows.Media; /// /// An element contained in a <GlobalStyles> element. /// [Serializable] public class XshtdGlobalStyle : XshtdElement { #region fields private readonly XshtdGlobalStyles _styles; #endregion fields #region ctors /// /// Creates a new XshtdSyntaxDefinition object. /// /// Parent collection of styles in which this style occurs. public XshtdGlobalStyle(XshtdGlobalStyles styles) : this() { _styles = styles; } /// /// Hidden class constructor /// protected XshtdGlobalStyle() { } #endregion ctors /// /// Gets/sets the style definition name /// public string TypeName { get; set; } /// /// Gets/sets the style definition name /// public Color? foreground { get; set; } /// /// Gets/sets the style definition name /// public Color? background { get; set; } /// /// Gets/sets the style definition name /// public Color? bordercolor { get; set; } #region methods /// /// Applies the visitor to this element. /// /// /// public override object AcceptVisitor(IXshtdVisitor visitor) { return visitor.VisitGlobalStyle(_styles, this); } #endregion methods } } ================================================ FILE: src/HL/Xshtd/XshtdGlobalStyles.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - © Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- #pragma warning disable namespace HL.Xshtd { using System; using System.Collections.Generic; using ICSharpCode.AvalonEdit.Utils; /// /// A <GlobalStyles> element. /// [Serializable] public class XshtdGlobalStyles : XshtdElement { /// /// Creates a new XshtdSyntaxDefinition object. /// public XshtdGlobalStyles() { this.Elements = new NullSafeCollection(); } /// /// Gets the collection of elements. /// public IList Elements { get; private set; } /// /// Applies the visitor to all elements. /// public void AcceptElements(IXshtdVisitor visitor) { foreach (XshtdElement element in Elements) { element.AcceptVisitor(visitor); } } /// /// Applies the visitor to this element. /// /// /// public override object AcceptVisitor(IXshtdVisitor visitor) { return visitor.VisitGlobalStyles(this); } } } ================================================ FILE: src/HL/Xshtd/XshtdSyntaxDefinition.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - © Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- #pragma warning disable // Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team // // Permission is hereby granted, free of charge, to any person obtaining a copy of this // software and associated documentation files (the "Software"), to deal in the Software // without restriction, including without limitation the rights to use, copy, modify, merge, // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons // to whom the Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all copies or // substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE // FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. namespace HL.Xshtd { using System; using System.Collections.Generic; using ICSharpCode.AvalonEdit.Utils; /// /// A <SyntaxDefinition> Xml element. /// [Serializable] public class XshtdSyntaxDefinition : XshtdElement { /// /// Creates a new XshtdSyntaxDefinition object. /// public XshtdSyntaxDefinition() { this.Elements = new NullSafeCollection(); this.Extensions = new NullSafeCollection(); } /// /// Gets/sets the definition name /// public string Name { get; set; } /// /// Gets the associated extensions. /// public IList Extensions { get; private set; } /// /// Gets the collection of elements. /// public IList Elements { get; private set; } /// /// Applies the visitor to all elements. /// public void AcceptElements(IXshtdVisitor visitor) { foreach (XshtdElement element in Elements) { element.AcceptVisitor(visitor); } } /// /// Applies the visitor to this element. /// /// /// public override object AcceptVisitor(IXshtdVisitor visitor) { return visitor.VisitSyntaxDefinition(this); } } } ================================================ FILE: src/HL/Xshtd/interfaces/IFreezable.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - © Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- #pragma warning disable // Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team // // Permission is hereby granted, free of charge, to any person obtaining a copy of this // software and associated documentation files (the "Software"), to deal in the Software // without restriction, including without limitation the rights to use, copy, modify, merge, // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons // to whom the Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all copies or // substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE // FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. namespace HL.Xshtd.interfaces { using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; /// /// Defines a freezable base for all objects that should be freezable. /// Frozen instances are immutable and thus thread-safe. /// interface IFreezable { /// /// Gets if this instance is frozen. Frozen instances are immutable and thus thread-safe. /// bool IsFrozen { get; } /// /// Freezes this instance. /// void Freeze(); } static class FreezableHelper { public static void ThrowIfFrozen(IFreezable freezable) { if (freezable.IsFrozen) throw new InvalidOperationException("Cannot mutate frozen " + freezable.GetType().Name); } public static IList FreezeListAndElements(IList list) { if (list != null) { foreach (T item in list) Freeze(item); } return FreezeList(list); } public static IList FreezeList(IList list) { if (list == null || list.Count == 0) return new T[0]; if (list.IsReadOnly) { // If the list is already read-only, return it directly. // This is important, otherwise we might undo the effects of interning. return list; } else { return new ReadOnlyCollection(list.ToArray()); } } public static void Freeze(object item) { IFreezable f = item as IFreezable; if (f != null) f.Freeze(); } public static T FreezeAndReturn(T item) where T : IFreezable { item.Freeze(); return item; } /// /// If the item is not frozen, this method creates and returns a frozen clone. /// If the item is already frozen, it is returned without creating a clone. /// public static T GetFrozenClone(T item) where T : IFreezable, ICloneable { if (!item.IsFrozen) { item = (T)item.Clone(); item.Freeze(); } return item; } } /// /// Implements a freezable base for all objects that should be freezable. /// Frozen instances are immutable and thus thread-safe. /// [Serializable] public abstract class AbstractFreezable : IFreezable { private bool isFrozen; /// /// Gets if this instance is frozen. Frozen instances are immutable and thus thread-safe. /// public bool IsFrozen { get { return isFrozen; } } /// /// Freezes this instance. /// public void Freeze() { if (!isFrozen) { FreezeInternal(); isFrozen = true; } } /// /// Provides a way of freezing additional elements defined in inheriting /// classes through the invocation of the method. /// protected virtual void FreezeInternal() { } } } ================================================ FILE: src/HL/Xshtd/interfaces/IHighlightingDefinitionReferenceResolver.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- #pragma warning disable namespace HL.Xshtd.interfaces { using HL.HighlightingTheme; /// /// Defines a resolver interface that can find highlighting theme definitions /// based on a highlighting name (searches within the current highlighting theme) /// or based on a highlighting name and name of highlighting theme that should /// contain the highlighting definition. /// public interface IHighlightingThemeDefinitionReferenceResolver { /// /// Gets a highlighting definition within the current highlighting theme /// by name, or null. /// /// /// SyntaxDefinition GetThemeDefinition(string highlightingName); /// /// Gets a highlighting theme definition by name from a given highlighting /// theme obtained via or null. /// /// /// SyntaxDefinition GetThemeDefinition(string hlThemeName, string highlightingName); } } ================================================ FILE: src/HL/Xshtd/interfaces/IHighlightingThemeDefinition.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- #pragma warning disable namespace HL.Xshtd.interfaces { using HL.HighlightingTheme; using System.Collections.Generic; /// /// A highlighting definition. /// public interface IHighlightingThemeDefinition { /// /// Gets the name of the highlighting theme definition. /// string Name { get; } /// /// Gets a named highlighting color. /// /// The highlighting color, or null if it is not found. ////HighlightingColor GetNamedColor(string name); SyntaxDefinition GetNamedSyntaxDefinition(string name); /// /// Gets all global stayles in the collection of global styles. /// IEnumerable GlobalStyles { get; } } } ================================================ FILE: src/StartMenuManager.Builder/App.config ================================================ ================================================ FILE: src/StartMenuManager.Builder/Program.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - © Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- using System; using System.IO; using IWshRuntimeLibrary; using Newtonsoft.Json; using StartMenuManager.Core.DataStructures; using StartMenuManager.Core.Serialization; namespace StartMenuManager.Builder { public class Program { private static string jsonFilePath; private static SettingsConfig settings; public static void Main(string[] args) { string settingsPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"..\settings.json"); if (System.IO.File.Exists(settingsPath)) { StreamReader reader = new StreamReader(settingsPath); string contents = reader.ReadToEnd(); reader.Close(); settings = JsonConvert.DeserializeObject(contents); } else { settings = SettingsConfig.GetDefaultSettings(); } if (!GetJsonFilePath(args)) { if (!CouldFindJsonFileInDirectory()) { Console.WriteLine("Error: Could not find 'shortcuts.json'"); Console.WriteLine("Please provide path to 'shortcuts.json' as command line argument."); return; } } string fileContents = GetFileContents(); Config config = Serializer.DeserializeConfig(fileContents); if (config == null) { Console.WriteLine("Error: Not valid JSON!"); return; } ValidationError err = config.IsValid(); if (err != null) { Console.WriteLine("Error: One or more shortcuts within JSON file are not valid!"); Console.WriteLine("More Details:"); Console.WriteLine($"Shortcut \"{err.Shortcut.Name}\":{err.Error}"); return; } if (!Directory.Exists(settings.StartMenuFolder)) { Console.WriteLine("Error: Could not find Start Menu Folder"); return; } if (!Directory.Exists(settings.GetShortcutsFilePath())) { Directory.CreateDirectory(settings.GetShortcutsFilePath()); } else { ClearDirectoryExceptShortcutsJson(settings.GetShortcutsFilePath()); } foreach (Shortcut shortcut in config.Shortcuts) { BuildShortcutFile(shortcut); } Console.WriteLine("All done!"); } public static void BuildShortcutFile(Shortcut shortcut) { // Build text file string shortcutJson = Serializer.SerializeShortcut(shortcut); string shortcutTextFilePath = settings.GetShortcutsFilePath($"{shortcut.Name}.txt"); StreamWriter writer = new StreamWriter(shortcutTextFilePath, false); writer.Write(shortcutJson); writer.Close(); // Copy icon string iconFilePath = settings.GetShortcutsFilePath($"{shortcut.Name}.ico"); bool gotIcon = CopyIcon(shortcut.IconPath, iconFilePath); // Create shortcut string runnerPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"..\Runner\StartMenuManager.Runner.exe"); string shortcutFilePath = settings.GetShortcutsFilePath($"{shortcut.Name}.lnk"); WshShell shell = new WshShell(); IWshShortcut wshShortcut = (IWshShortcut)shell.CreateShortcut(shortcutFilePath); if (gotIcon) { wshShortcut.IconLocation = iconFilePath; } wshShortcut.TargetPath = $"{runnerPath}"; wshShortcut.Arguments = $"\"{shortcutTextFilePath}\""; wshShortcut.Save(); } public static bool CopyIcon(string iconPath, string newIconPath) { if (string.IsNullOrEmpty(iconPath)) { return false; } if (Path.GetExtension(iconPath) != ".ico") { return false; } if (!System.IO.File.Exists(iconPath)) { return false; } System.IO.File.Copy(iconPath, newIconPath); return true; } public static bool GetJsonFilePath(string[] args) { if (args != null) { if (args.Length > 0) { string possiblePath = args[0]; if (System.IO.File.Exists(possiblePath)) { jsonFilePath = possiblePath; return true; } } } return false; } public static bool CouldFindJsonFileInDirectory() { string possiblePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "shortcuts.json"); if (System.IO.File.Exists(possiblePath)) { jsonFilePath = possiblePath; return true; } return false; } public static string GetFileContents() { StreamReader reader = new StreamReader(jsonFilePath); string contents = reader.ReadToEnd(); reader.Close(); return contents; } public static void ClearDirectoryExceptShortcutsJson(string path) { System.IO.DirectoryInfo di = new DirectoryInfo(path); foreach (FileInfo file in di.GetFiles()) { if (file.Name == "shortcuts.json") { continue; } file.Delete(); } foreach (DirectoryInfo dir in di.GetDirectories()) { dir.Delete(true); } } } } ================================================ FILE: src/StartMenuManager.Builder/Properties/AssemblyInfo.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - © Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- using System.Reflection; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("StartMenuManager.Builder")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("StartMenuManager.Builder")] [assembly: AssemblyCopyright("Copyright © 2020")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("72692f58-2690-4677-a87b-a686bcaa6ff2")] // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] ================================================ FILE: src/StartMenuManager.Builder/StartMenuManager.Builder.csproj ================================================  Debug AnyCPU {72692F58-2690-4677-A87B-A686BCAA6FF2} Exe StartMenuManager.Builder StartMenuManager.Builder v4.7.2 512 true true publish\ true Disk false Foreground 7 Days false false true 0 1.0.0.%2a false false true AnyCPU true full false bin\Debug\ DEBUG;TRACE prompt 4 AnyCPU pdbonly true bin\Release\ TRACE prompt 4 icon-256.ico False Microsoft .NET Framework 4.6 %28x86 and x64%29 true False .NET Framework 3.5 SP1 false {f027fcb2-cc37-4d24-a2ab-072e19b87a18} StartMenuManager.Core {F935DC20-1CF0-11D0-ADB9-00C04FD58A0B} 1 0 0 tlbimp False True 12.0.3 ================================================ FILE: src/StartMenuManager.Core/DataStructures/Action.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - © Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- using System; using JsonSubTypes; using Newtonsoft.Json; using StartMenuManager.Core.DataStructures.Actions; namespace StartMenuManager.Core.DataStructures { /// /// An Action for use within a Shortcut. /// [JsonConverter(typeof(JsonSubtypes), "Type")] [JsonSubtypes.KnownSubType(typeof(CommandAction), "command")] [JsonSubtypes.KnownSubType(typeof(FileAction), "file")] [JsonSubtypes.KnownSubType(typeof(FolderAction), "folder")] [JsonSubtypes.KnownSubType(typeof(SoftwareAction), "software")] [JsonSubtypes.KnownSubType(typeof(WebsiteAction), "website")] public class Action { public string Type { get; set; } public virtual ValidationError IsValid() { return null; } public virtual Action Duplicate() { throw new NotImplementedException("Action base class cannot be duplicated."); } } } ================================================ FILE: src/StartMenuManager.Core/DataStructures/Actions/CommandAction.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - © Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- namespace StartMenuManager.Core.DataStructures.Actions { /// /// Action which executes a command using Command Prompt. /// public class CommandAction : Action { public CommandAction(string command, bool keepOpen) { Type = "command"; Command = command; KeepOpen = keepOpen; } public CommandAction() { Type = "command"; Command = string.Empty; KeepOpen = true; } public string Command { get; set; } public bool KeepOpen { get; set; } public override ValidationError IsValid() { if (string.IsNullOrEmpty(Command)) { return new ValidationError("Command cannot be empty!", this); } return null; } public override Action Duplicate() { return new CommandAction(Command, KeepOpen); } } } ================================================ FILE: src/StartMenuManager.Core/DataStructures/Actions/FileAction.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - © Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- using System.IO; namespace StartMenuManager.Core.DataStructures.Actions { /// /// Action which opens a file with the default software for that file type. /// public class FileAction : Action { public FileAction(string path) { Type = "file"; Path = path; } public FileAction() { Type = "file"; Path = string.Empty; } public string Path { get; set; } public override ValidationError IsValid() { if (string.IsNullOrEmpty(Path)) { return new ValidationError("File Path cannot be empty!", this); } if (IsFolder(Path)) { return new ValidationError("Need File path, not folder path!", this); } if (!File.Exists(Path)) { return new ValidationError("File Path does not exist!", this); } return null; } private static bool IsFolder(string path) { try { FileAttributes attr = File.GetAttributes(path); if ((attr & FileAttributes.Directory) == FileAttributes.Directory) { return true; } } catch { return false; } return false; } public override Action Duplicate() { return new FileAction(Path); } } } ================================================ FILE: src/StartMenuManager.Core/DataStructures/Actions/FolderAction.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - © Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- using System.IO; namespace StartMenuManager.Core.DataStructures.Actions { /// /// Action which opens a file with the default software for that file type. /// public class FolderAction : Action { public FolderAction(string path) { Type = "folder"; Path = path; } public FolderAction() { Type = "folder"; Path = string.Empty; } public string Path { get; set; } public override ValidationError IsValid() { if (string.IsNullOrEmpty(Path)) { return new ValidationError("Folder Path cannot be empty!", this); } if (IsFile(Path)) { return new ValidationError("Need Folder path, not file path!", this); } if (!Directory.Exists(Path)) { return new ValidationError("Folder does not exist!", this); } return null; } private static bool IsFile(string path) { if (System.IO.Path.HasExtension(path)) { return true; } return false; } public override Action Duplicate() { return new FolderAction(Path); } } } ================================================ FILE: src/StartMenuManager.Core/DataStructures/Actions/SoftwareAction.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - © Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- using System.IO; namespace StartMenuManager.Core.DataStructures.Actions { /// /// Action which opens software, usually a .exe file. /// public class SoftwareAction : Action { public SoftwareAction(string path) { Type = "software"; Path = path; } public SoftwareAction() { Type = "software"; Path = string.Empty; } public string Path { get; set; } public override ValidationError IsValid() { if (string.IsNullOrEmpty(Path)) { return new ValidationError("Software Path cannot be empty!", this); } if (!File.Exists(Path)) { return new ValidationError("Software Start File does not exist!", this); } return null; } public override Action Duplicate() { return new SoftwareAction(Path); } } } ================================================ FILE: src/StartMenuManager.Core/DataStructures/Actions/WebsiteAction.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - © Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- using System; namespace StartMenuManager.Core.DataStructures.Actions { /// /// Action which opens a URL within a specified web browser. /// public class WebsiteAction : Action { public WebsiteAction(string url) { Type = "website"; Url = url; } public WebsiteAction() { Type = "website"; Url = "https://google.com"; } public string Url { get; set; } public override ValidationError IsValid() { Uri uriResult; if (!Uri.TryCreate(Url, UriKind.Absolute, out uriResult)) { return new ValidationError("Url not valid!", this); } if (uriResult.Scheme != Uri.UriSchemeHttp && uriResult.Scheme != Uri.UriSchemeHttps) { return new ValidationError("Url should start with 'http'!", this); } return null; } public override Action Duplicate() { return new WebsiteAction(Url); } } } ================================================ FILE: src/StartMenuManager.Core/DataStructures/Config.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - © Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- using System.Collections.Generic; namespace StartMenuManager.Core.DataStructures { /// /// A full shortcut configuration (equivalent to the JSON file) /// public class Config { public Config(List shortcuts) { Shortcuts = shortcuts; } public Config() { Shortcuts = new List(); } public List Shortcuts { get; set; } public ValidationError IsValid() { List names = new List(); foreach (Shortcut shortcut in Shortcuts) { ValidationError shortcutErr = shortcut.IsValid(); if (shortcutErr != null) { return shortcutErr; } if (names.Contains(shortcut.Name)) { return new ValidationError("Duplicate Shortcut Name Found!", shortcut); } names.Add(shortcut.Name); } return null; } } } ================================================ FILE: src/StartMenuManager.Core/DataStructures/SettingsConfig.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - © Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- using System.IO; namespace StartMenuManager.Core.DataStructures { public class SettingsConfig { public string StartMenuFolder { get; set; } public string SmmShortcutsFolder { get; set; } public bool DisplayWelcomeBox { get; set; } public string Theme { get; set; } public bool JsonLineNumbers { get; set; } public bool YesNoDialogsEnabled { get; set; } public int NumberOfUsesUntilMessage { get; set; } public string GetShortcutsFilePath(string fileName) { return Path.Combine(StartMenuFolder, SmmShortcutsFolder, fileName); } public string GetShortcutsFilePath() { return Path.Combine(StartMenuFolder, SmmShortcutsFolder); } public static SettingsConfig GetDefaultSettings() { SettingsConfig settings = new SettingsConfig(); settings.StartMenuFolder = @"C:\ProgramData\Microsoft\Windows\Start Menu\Programs"; settings.SmmShortcutsFolder = "SmmShortcuts"; settings.DisplayWelcomeBox = true; settings.Theme = "default"; settings.JsonLineNumbers = false; settings.YesNoDialogsEnabled = true; settings.NumberOfUsesUntilMessage = 4; return settings; } } } ================================================ FILE: src/StartMenuManager.Core/DataStructures/Shortcut.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - © Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- using System.Collections.Generic; using StartMenuManager.Core.DataStructures.Actions; namespace StartMenuManager.Core.DataStructures { /// /// A Shortcut for use within a Config /// public class Shortcut { public Shortcut(string name, string iconPath, List actions) { Name = name; IconPath = iconPath; Actions = actions; } public Shortcut(string name, string iconPath) { Name = name; IconPath = iconPath; Actions = new List(); } public Shortcut() { Actions = new List(); } public string IconPath { get; set; } public string Name { get; set; } public List Actions { get; set; } public ValidationError IsValid() { if (string.IsNullOrEmpty(Name)) { return new ValidationError("Shortcut Name Cannot be Empty.", this); } foreach (Action action in Actions) { switch (action.Type) { case "command": CommandAction a1 = action as CommandAction; ValidationError a1Err = a1.IsValid(); if (a1Err != null) { a1Err.Shortcut = this; return a1Err; } break; case "file": FileAction a2 = action as FileAction; ValidationError a2Err = a2.IsValid(); if (a2Err != null) { a2Err.Shortcut = this; return a2Err; } break; case "folder": FolderAction a3 = action as FolderAction; ValidationError a3Err = a3.IsValid(); if (a3Err != null) { a3Err.Shortcut = this; return a3Err; } break; case "software": SoftwareAction a4 = action as SoftwareAction; ValidationError a4Err = a4.IsValid(); if (a4Err != null) { a4Err.Shortcut = this; return a4Err; } break; case "website": WebsiteAction a5 = action as WebsiteAction; ValidationError a5Err = a5.IsValid(); if (a5Err != null) { a5Err.Shortcut = this; return a5Err; } break; } } return null; } public Shortcut Duplicate() { List duplicateActions = new List(); foreach (Action action in Actions) { duplicateActions.Add(action.Duplicate()); } return new Shortcut(Name, IconPath, duplicateActions); } } } ================================================ FILE: src/StartMenuManager.Core/DataStructures/ValidationError.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - © Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- namespace StartMenuManager.Core.DataStructures { public class ValidationError { public ValidationError(string error, Action action) { Error = error; Action = action; } public ValidationError(string error, Shortcut shortcut) { Error = error; Shortcut = shortcut; } public Action Action { get; set; } public Shortcut Shortcut { get; set; } public string Error { get; set; } } } ================================================ FILE: src/StartMenuManager.Core/Serialization/Serializer.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - © Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- using Newtonsoft.Json; using StartMenuManager.Core.DataStructures; namespace StartMenuManager.Core.Serialization { /// /// Serialization methods for Configs /// public static class Serializer { public static string SerializeConfig(Config config) { return JsonConvert.SerializeObject(config, Formatting.Indented); } public static Config DeserializeConfig(string configText) { return JsonConvert.DeserializeObject(configText); } public static string SerializeShortcut(Shortcut shorcut) { return JsonConvert.SerializeObject(shorcut, Formatting.Indented); } public static Shortcut DeserializeShortcut(string shortcutText) { return JsonConvert.DeserializeObject(shortcutText); } } } ================================================ FILE: src/StartMenuManager.Core/StartMenuManager.Core.csproj ================================================ netstandard2.0 all runtime; build; native; contentfiles; analyzers; buildtransitive ================================================ FILE: src/StartMenuManager.GUI/App.config ================================================ ================================================ FILE: src/StartMenuManager.GUI/App.xaml ================================================  ================================================ FILE: src/StartMenuManager.GUI/App.xaml.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - © Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- using System.Windows; namespace StartMenuManager.GUI { /// /// Interaction logic for App.xaml /// public partial class App : Application { } } ================================================ FILE: src/StartMenuManager.GUI/Builder.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - © Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- using System; using System.Diagnostics; using System.IO; using StartMenuManager.Core.DataStructures; using StartMenuManager.Core.Serialization; using StartMenuManager.GUI.Dialogs; using StartMenuManager.GUI.Serialization; namespace StartMenuManager.GUI { public static class Builder { public static void Run(Config config) { WindowRef.Wind.Settings.NumberOfUsesUntilMessage--; if (WindowRef.Wind.Settings.NumberOfUsesUntilMessage == 0) { WindowRef.Wind.Settings.NumberOfUsesUntilMessage = 4; YesNoDialog.SetMessage("Please Consider Donating.", "It took a lot of time to make this software available for free. If you like it, please consider making a donation to show your appreciation.", "Donate", "Ignore", (b) => ContinueRun(config, b)); DialogManager.Show(Structures.DialogTypes.YesNoDialog); Serialization.JsonSerializer.SaveSettings(WindowRef.Wind.Settings); return; } Serialization.JsonSerializer.SaveSettings(WindowRef.Wind.Settings); ContinueRun(config, false); } private static void ContinueRun(Config config, bool donate) { if (donate) { System.Diagnostics.Process.Start(@"https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=MLD56V6HQWCKU&source=url"); } string configJson = Serializer.SerializeConfig(config); JsonSerializer.SaveLastShortcutsJson(configJson); string builderPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Builder", "StartMenuManager.Builder.exe"); string shortcutsJsonPath = WindowRef.Wind.Settings.GetShortcutsFilePath("shortcuts.json"); ExecuteAsAdmin(builderPath, shortcutsJsonPath); // Remove old website icons IconManager.ClearUnusedIcons(config); } private static void ExecuteAsAdmin(string fileName, string arguments) { Process proc = new Process(); proc.StartInfo.FileName = fileName; proc.StartInfo.UseShellExecute = true; proc.StartInfo.Arguments = $"\"{arguments}\""; proc.StartInfo.Verb = "runas"; proc.Start(); } } } ================================================ FILE: src/StartMenuManager.GUI/Dialogs/MessageDialog.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - © Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- using System.Windows; using static StartMenuManager.GUI.WindowRef; namespace StartMenuManager.GUI.Dialogs { public static class MessageDialog { public static void InitEvents() { Wind.MessageDialog_CloseButton.Click += (sender, args) => CloseDialog(sender, args); } public static void SetMessage(string title, string message) { Wind.MessageDialog_Message.Text = message; Wind.MessageDialog_Title.Text = title; } public static void CloseDialog(object sender, RoutedEventArgs args) { if (DialogManager.OpenDialogSession != null) { DialogManager.OpenDialogSession.Close(); DialogManager.OpenDialogSession = null; } } } } ================================================ FILE: src/StartMenuManager.GUI/Dialogs/SettingsDialog.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - © Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- using System.Diagnostics; using System.IO; using System.Windows; using static StartMenuManager.GUI.WindowRef; namespace StartMenuManager.GUI.Dialogs { public static class SettingsDialog { private static bool eventBlock = false; public static void InitEvents() { Wind.SettingsDialog_CloseButton.Click += (sender, args) => CloseDialog(sender, args); Wind.SettingsDialog_OpenFolderButton.Click += (sender, args) => OpenStartMenuFolder(sender, args); Wind.SettingsDialog_GitHubButton.Click += (sender, args) => OpenGitHubPage(sender, args); Wind.SettingsDialog_LineNumbersCheckbox.Checked += (sender, args) => LineNumbersChanged(true); Wind.SettingsDialog_LineNumbersCheckbox.Unchecked += (sender, args) => LineNumbersChanged(false); Wind.SettingsDialog_YesNoCheckbox.Checked += (sender, args) => ShowConfirmationDialogsChanged(true); Wind.SettingsDialog_YesNoCheckbox.Unchecked += (sender, args) => ShowConfirmationDialogsChanged(false); Wind.SettingsDialog_ThemeComboBox.SelectionChanged += (sender, args) => ThemeChanged(sender, args); } public static void InitDialog() { if (!Directory.Exists(WindowRef.Wind.Settings.GetShortcutsFilePath())) { Wind.SettingsDialog_NumOfShortcuts.Text = "0"; } else { string[] files = Directory.GetFiles(WindowRef.Wind.Settings.GetShortcutsFilePath(), "*.lnk"); Wind.SettingsDialog_NumOfShortcuts.Text = files.Length.ToString(); } if (Wind.Settings.Theme == "dark" && Wind.SettingsDialog_ThemeComboBox.SelectedIndex != 0) { eventBlock = true; Wind.SettingsDialog_ThemeComboBox.SelectedIndex = 0; } if (Wind.Settings.Theme == "light" && Wind.SettingsDialog_ThemeComboBox.SelectedIndex != 1) { eventBlock = true; Wind.SettingsDialog_ThemeComboBox.SelectedIndex = 1; } if (Wind.Settings.Theme == "default" && Wind.SettingsDialog_ThemeComboBox.SelectedIndex != 2) { eventBlock = true; Wind.SettingsDialog_ThemeComboBox.SelectedIndex = 2; } if (Wind.Settings.YesNoDialogsEnabled != Wind.SettingsDialog_YesNoCheckbox.IsChecked) { eventBlock = true; Wind.SettingsDialog_YesNoCheckbox.IsChecked = Wind.Settings.YesNoDialogsEnabled; } if (Wind.Settings.JsonLineNumbers != Wind.SettingsDialog_LineNumbersCheckbox.IsChecked) { eventBlock = true; Wind.SettingsDialog_LineNumbersCheckbox.IsChecked = Wind.Settings.JsonLineNumbers; } } public static void CloseDialog(object sender, RoutedEventArgs args) { if (DialogManager.OpenDialogSession != null) { DialogManager.OpenDialogSession.Close(); DialogManager.OpenDialogSession = null; } } public static void OpenStartMenuFolder(object sender, RoutedEventArgs args) { if (Directory.Exists(WindowRef.Wind.Settings.GetShortcutsFilePath())) { Process.Start(WindowRef.Wind.Settings.GetShortcutsFilePath()); return; } if (Directory.Exists(WindowRef.Wind.Settings.StartMenuFolder)) { Process.Start(WindowRef.Wind.Settings.StartMenuFolder); } } public static void OpenGitHubPage(object sender, RoutedEventArgs args) { Process.Start("https://github.com/James231/Start-Menu-Manager"); } public static void ThemeChanged(object sender, RoutedEventArgs args) { if (eventBlock) { eventBlock = false; return; } switch (Wind.SettingsDialog_ThemeComboBox.SelectedIndex) { case 0: ThemeManager.SetDarkTheme(); Wind.Settings.Theme = "dark"; break; case 1: ThemeManager.SetLightTheme(); Wind.Settings.Theme = "light"; break; case 2: ThemeManager.SetSystemTheme(); Wind.Settings.Theme = "default"; break; } Serialization.JsonSerializer.SaveSettings(Wind.Settings); } public static void LineNumbersChanged(bool show) { if (eventBlock) { eventBlock = false; return; } JsonViewManager.ShowLineNumbers(show); Wind.Settings.JsonLineNumbers = show; Serialization.JsonSerializer.SaveSettings(Wind.Settings); } public static void ShowConfirmationDialogsChanged(bool show) { if (eventBlock) { eventBlock = false; return; } Wind.Settings.YesNoDialogsEnabled = show; Serialization.JsonSerializer.SaveSettings(Wind.Settings); } } } ================================================ FILE: src/StartMenuManager.GUI/Dialogs/YesNoDialog.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - © Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- using System.Windows; using static StartMenuManager.GUI.WindowRef; namespace StartMenuManager.GUI.Dialogs { public static class YesNoDialog { private static Callback response; public delegate void Callback(bool isYes); public static void InitEvents() { Wind.YesNoDialog_YesButton.Click += (sender, args) => YesButtonPressed(sender, args); Wind.YesNoDialog_NoButton.Click += (sender, args) => NoButtonPressed(sender, args); } public static void SetMessage(string title, string message, string yesText, string noText, Callback isYes) { Wind.YesNoDialog_YesButton.Content = yesText; Wind.YesNoDialog_NoButton.Content = noText; Wind.YesNoDialog_Message.Text = message; Wind.YesNoDialog_Title.Text = title; response = isYes; } public static void YesButtonPressed(object sender, RoutedEventArgs args) { CloseDialog(); response.Invoke(true); } public static void NoButtonPressed(object sender, RoutedEventArgs args) { CloseDialog(); response.Invoke(false); } private static void CloseDialog() { if (DialogManager.OpenDialogSession != null) { DialogManager.OpenDialogSession.Close(); DialogManager.OpenDialogSession = null; } } } } ================================================ FILE: src/StartMenuManager.GUI/Extensions/ActionExtensions.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - © Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- using StartMenuManager.Core.DataStructures; using StartMenuManager.Core.DataStructures.Actions; using StartMenuManager.GUI.Structures; namespace StartMenuManager.GUI.Extensions { public static class ActionExtensions { public static ShortcutType ToShortcutType(this Action action) { if (action is FileAction) { return ShortcutType.File; } if (action is FolderAction) { return ShortcutType.Folder; } if (action is SoftwareAction) { return ShortcutType.Software; } if (action is CommandAction) { return ShortcutType.Command; } return ShortcutType.Web; } } } ================================================ FILE: src/StartMenuManager.GUI/IconExtractorWindow.xaml ================================================  https://... Not a valid website Uri. Should start with 'http://' or 'https://'. Loading ... ================================================ FILE: src/StartMenuManager.GUI/IconExtractorWindow.xaml.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - © Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- #pragma warning disable using System; using System.ComponentModel; using System.IO; using System.Threading; using System.Windows; using System.Windows.Controls; using System.Windows.Media.Imaging; using ImageMagick; using WebImageExtractor; namespace StartMenuManager.GUI { /// /// Interaction logic for IconExtractorWindow.xaml /// public partial class IconExtractorWindow : Window { private int numRunning = 0; private MainWindow window; private ShortcutControl shortcutControl; public IconExtractorWindow(MainWindow mainWindow, ShortcutControl control) { window = mainWindow; shortcutControl = control; InitializeComponent(); IconExtractorWindow_TitleBarControl.InitEvents(this); Loaded += (s, e) => { Closing += OnWindowClose; }; } private static IconExtractorWindow CurrentWindow { get; set; } private static CancellationTokenSource cancellationTokenSource; public static void CreateOrFocusInstance(MainWindow window, ShortcutControl control) { if (CurrentWindow != null) { if (ContainsWindow(Application.Current.Windows, CurrentWindow)) { CurrentWindow.Focus(); return; } } CurrentWindow = new IconExtractorWindow(window, control); CurrentWindow.Show(); } public static bool FocusInstance() { if (CurrentWindow != null) { if (ContainsWindow(Application.Current.Windows, CurrentWindow)) { CurrentWindow.Focus(); return true; } } return false; } private static bool ContainsWindow(WindowCollection windows, Window myWindow) { foreach (Window w in windows) { if (w == myWindow) { return true; } } return false; } private void OnWindowClose(object sender, CancelEventArgs e) { if (cancellationTokenSource != null) { cancellationTokenSource.Cancel(); } } private async void SearchButtonPressed(object sender, RoutedEventArgs e) { if (!UrlInput.Text.StartsWith("http://") && !UrlInput.Text.StartsWith("https://")) { ErrorText.Visibility = Visibility.Visible; LoadingSpinner.Visibility = Visibility.Collapsed; return; } ErrorText.Visibility = Visibility.Collapsed; LoadingSpinner.Visibility = Visibility.Visible; ExtractionSettings settings = new ExtractionSettings() { SvgOnly = false, RecurseUri = true, RecurseHyperlinks = true, HyperlinkRecursionDepth = 3, LazyDownload = true, GetMetaTagImages = true, GetLinkTagImages = true, GetInlineBackgroundImages = true, UseCorsAnywhere = false, DisableValidityCheck = false, }; settings.OnFoundImage += async (WebImage image) => { try { MagickImage img = await image.GetImageAsync(); if (img.Format != MagickFormat.Svg) { if (img.Width < 64 || img.Height < 64 || img.Width > 512 || img.Height > 512) { return; } var size = new MagickGeometry(256, 256); size.IgnoreAspectRatio = false; img.Resize(size); MagickColor mc = new MagickColor(0, 0, 0, 0); img.Transparent(mc); img.Format = MagickFormat.Bmp; } else { Density de = new Density(256, 256); MagickColor mc = new MagickColor(0, 0, 0, 0); img.Transparent(mc); img.Density = de; img.Settings.TextAntiAlias = true; img.Format = MagickFormat.Bmp; } byte[] bytes = img.ToByteArray(); BitmapImage bitmapImage = LoadImage(bytes); ListBoxItem boxItem = new ListBoxItem(); Image imageControl = new Image(); imageControl.Width = 96; imageControl.Height = 96; imageControl.Source = bitmapImage; boxItem.Content = imageControl; boxItem.Selected += (s, args) => { window.SelectedWebsiteImage(img, shortcutControl); Close(); }; ImageParent.Items.Add(boxItem); } catch (Exception) { } }; ImageParent.Items.Clear(); if (cancellationTokenSource != null) { cancellationTokenSource.Cancel(); } numRunning++; cancellationTokenSource = new CancellationTokenSource(); try { await Extractor.GetAllImages(UrlInput.Text.Trim(), settings, cancellationTokenSource.Token); } catch (Exception) { } numRunning--; if (numRunning == 0) { LoadingSpinner.Visibility = Visibility.Collapsed; } } private static BitmapImage LoadImage(byte[] imageData) { if (imageData == null || imageData.Length == 0) { return null; } var image = new BitmapImage(); using (var mem = new MemoryStream(imageData)) { mem.Position = 0; image.BeginInit(); image.CreateOptions = BitmapCreateOptions.PreservePixelFormat; image.CacheOption = BitmapCacheOption.OnLoad; image.UriSource = null; image.StreamSource = mem; image.EndInit(); } image.Freeze(); return image; } } } ================================================ FILE: src/StartMenuManager.GUI/JsonViewManager.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - © Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- using System.Windows; using static StartMenuManager.GUI.WindowRef; namespace StartMenuManager.GUI { public static class JsonViewManager { private static string oldJson; public static void InitEvents() { Wind.JsonView_ResetJsonButton.Click += (sender, args) => ResetJsonButtonPressed(sender, args); } public static void Init() { InitEvents(); ShowLineNumbers(Wind.Settings.JsonLineNumbers); } public static void ShowLineNumbers(bool enabled) { Wind.textEditor.ShowLineNumbers = enabled; } public static void SetJson(string text) { oldJson = text; Wind.textEditor.Text = text; } public static void ResetJsonButtonPressed(object sender, RoutedEventArgs args) { Wind.textEditor.Text = oldJson; } } } ================================================ FILE: src/StartMenuManager.GUI/LowerMenuBar.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - © Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- using System.Windows; using StartMenuManager.Core.DataStructures; using StartMenuManager.Core.Serialization; using StartMenuManager.GUI.Dialogs; using StartMenuManager.GUI.Serialization; using static StartMenuManager.GUI.WindowRef; namespace StartMenuManager.GUI { public static class LowerMenuBar { public static void InitEvents() { Wind.LowerMenu_ResetButton.Click += (sender, args) => ResetButtonPressed(sender, args); Wind.LowerMenu_RemoveButton.Click += (sender, args) => RemoveAllButtonPressed(sender, args); Wind.LowerMenu_GenerateButton.Click += (sender, args) => GenerateShortcutsButtonPressed(sender, args); } public static void ResetButtonPressed(object sender, RoutedEventArgs args) { if (Wind.Settings.YesNoDialogsEnabled) { YesNoDialog.SetMessage("Are you sure?", "You will loose any changes.", "Yes", "No", ResetJson); DialogManager.Show(Structures.DialogTypes.YesNoDialog); } else { ResetJson(true); } } public static void RemoveAllButtonPressed(object sender, RoutedEventArgs args) { if (Wind.Settings.YesNoDialogsEnabled) { Dialogs.YesNoDialog.SetMessage("Are you sure?", "This will remove all Shortcuts you have entered?", "Yes", "No", RemoveAllConfirmation); DialogManager.Show(Structures.DialogTypes.YesNoDialog); } else { RemoveAllConfirmation(true); } } private static void RemoveAllConfirmation(bool isYes) { if (isYes) { ShortcutListArea.RemoveAllShortcuts(); Wind.ValiationError.Visibility = Visibility.Collapsed; } } public static void GenerateShortcutsButtonPressed(object sender, RoutedEventArgs args) { Config config = ShortcutListArea.GetConfig(); ValidationError err = config.IsValid(); if (err != null) { Wind.ValiationError.Visibility = Visibility.Visible; Wind.ValidationErrorText.Text = $"Error: \"{err.Shortcut.Name}\" {err.Error}"; return; } else { Wind.ValiationError.Visibility = Visibility.Collapsed; } Builder.Run(config); } private static void ResetJson(bool shouldReset) { if (shouldReset) { string getJson = JsonSerializer.GetLastShortcutsJson(); Config shortcutsConfig = null; try { shortcutsConfig = Serializer.DeserializeConfig(getJson); } catch { shortcutsConfig = new Config(); getJson = Serializer.SerializeConfig(shortcutsConfig); JsonSerializer.SaveLastShortcutsJson(getJson); } JsonViewManager.SetJson(getJson); ShortcutListArea.LoadShortcuts(shortcutsConfig.Shortcuts); Wind.ValiationError.Visibility = Visibility.Collapsed; } } } } ================================================ FILE: src/StartMenuManager.GUI/MainWindow.xaml ================================================  Settings Number of currently active shortcuts: 50 Theme: Dark Light System Default Json Line Numbers: Confirmation Dialogs Enabled: All start menu shortcuts are saved here: You can find updates and documentation on the GitHub page: Settings Settings Settings Settings Error: Some Message Welcome to Start Menu Manager! You can create and edit shortcuts to websites/software/files/folders below and press the generate button to add them to the Start Menu. You can pull icons from websites or use your own. Use the Settings icon on the title bar to edit application settings including the theme. After generating shortcuts, icons might not be displayed correctly in the Start Menu. This is a Windows bug. Temporarily changing the display scaling in Windows settings will fix this. See the documentation on GitHub for more information. Use the JSON View to obtain your shortcuts as JSON code. Use this to copy your shortcuts onto different devices. Please star the GitHub repository. Use it to report Issues, and check for updates. Thank you! Shortcuts: ================================================ FILE: src/StartMenuManager.GUI/MainWindow.xaml.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - © Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- using System.IO; using System.Windows; using ImageMagick; using StartMenuManager.Core.DataStructures; using StartMenuManager.Core.Serialization; using StartMenuManager.GUI.Serialization; namespace StartMenuManager.GUI { /// /// Interaction logic for MainWindow.xaml /// public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); WindowRef.Wind = this; Settings = JsonSerializer.GetSettings(); if (!Settings.DisplayWelcomeBox) { WelcomeCard.CloseCard(); } if (!CheckSettingsValid()) { Close(); return; } InitEvents(); ThemeManager.InitTheme(); InitJson(); } public SettingsConfig Settings { get; set; } private void InitEvents() { TitleBarControl.InitEvents(); TitleBarButtons.InitEvents(); WelcomeCard.InitEvents(); LowerMenuBar.InitEvents(); ShortcutListArea.InitEvents(); JsonViewManager.Init(); Dialogs.SettingsDialog.InitEvents(); Dialogs.MessageDialog.InitEvents(); Dialogs.YesNoDialog.InitEvents(); } private void InitJson() { string getJson = JsonSerializer.GetLastShortcutsJson(); Config shortcutsConfig = null; try { shortcutsConfig = Serializer.DeserializeConfig(getJson); } catch { shortcutsConfig = new Config(); getJson = Serializer.SerializeConfig(shortcutsConfig); JsonSerializer.SaveLastShortcutsJson(getJson); } JsonViewManager.SetJson(getJson); ShortcutListArea.LoadShortcuts(shortcutsConfig.Shortcuts); } private void Window_PreviewMouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e) { e.Handled = IconExtractorWindow.FocusInstance(); } private void Window_PreviewMouseMove(object sender, System.Windows.Input.MouseEventArgs e) { e.Handled = IconExtractorWindow.FocusInstance(); } public void SelectedWebsiteImage(MagickImage image, ShortcutControl control) { image.Format = MagickFormat.Ico; string filePath = IconManager.SaveIcon(image, control.Shortcut.Name); control.IconSelectedEvent(filePath); } private bool CheckSettingsValid() { if (!Directory.Exists(Settings.StartMenuFolder)) { MessageBox.Show("Start Menu Folder not found. Please check the path in settings.json in the application install directory."); return false; } if (!Directory.Exists(Settings.GetShortcutsFilePath())) { Directory.CreateDirectory(Settings.GetShortcutsFilePath()); } return true; } } } ================================================ FILE: src/StartMenuManager.GUI/Properties/AssemblyInfo.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - © Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- using System.Reflection; using System.Runtime.InteropServices; using System.Windows; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("StartMenuManager.GUI")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("StartMenuManager.GUI")] [assembly: AssemblyCopyright("Copyright © 2020")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] // In order to begin building localizable applications, set // CultureYouAreCodingWith in your .csproj file // inside a . For example, if you are using US english // in your source files, set the to en-US. Then uncomment // the NeutralResourceLanguage attribute below. Update the "en-US" in // the line below to match the UICulture setting in the project file. // [assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] [assembly: ThemeInfo( ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly) ] // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] ================================================ FILE: src/StartMenuManager.GUI/Properties/Resources.Designer.cs ================================================ //------------------------------------------------------------------------------ // // This code was generated by a tool. // Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // //------------------------------------------------------------------------------ namespace StartMenuManager.GUI.Properties { using System; /// /// A strongly-typed resource class, for looking up localized strings, etc. /// // This class was auto-generated by the StronglyTypedResourceBuilder // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class Resources { private static global::System.Resources.ResourceManager resourceMan; private static global::System.Globalization.CultureInfo resourceCulture; [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal Resources() { } /// /// Returns the cached ResourceManager instance used by this class. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] internal static global::System.Resources.ResourceManager ResourceManager { get { if (object.ReferenceEquals(resourceMan, null)) { global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("StartMenuManager.GUI.Properties.Resources", typeof(Resources).Assembly); resourceMan = temp; } return resourceMan; } } /// /// Overrides the current thread's CurrentUICulture property for all /// resource lookups using this strongly typed resource class. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] internal static global::System.Globalization.CultureInfo Culture { get { return resourceCulture; } set { resourceCulture = value; } } } } ================================================ FILE: src/StartMenuManager.GUI/Properties/Resources.resx ================================================  text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 ================================================ FILE: src/StartMenuManager.GUI/Properties/Settings.Designer.cs ================================================ //------------------------------------------------------------------------------ // // This code was generated by a tool. // Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // //------------------------------------------------------------------------------ namespace StartMenuManager.GUI.Properties { [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.4.0.0")] internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); public static Settings Default { get { return defaultInstance; } } } } ================================================ FILE: src/StartMenuManager.GUI/Properties/Settings.settings ================================================  ================================================ FILE: src/StartMenuManager.GUI/Runner.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - © Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- using System; using System.Diagnostics; using System.IO; namespace StartMenuManager.GUI { public static class Runner { public static void Run(string filePath) { string runnerPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Runner", "StartMenuManager.Runner.exe"); ExecuteAsAdmin(runnerPath, filePath); } private static void ExecuteAsAdmin(string fileName, string arguments) { Process proc = new Process(); proc.StartInfo.FileName = fileName; proc.StartInfo.UseShellExecute = true; proc.StartInfo.Arguments = $"\"{arguments}\""; proc.StartInfo.Verb = "runas"; proc.Start(); } } } ================================================ FILE: src/StartMenuManager.GUI/Serialization/IconManager.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - © Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- using System; using System.Collections.Generic; using System.IO; using ImageMagick; using StartMenuManager.Core.DataStructures; namespace StartMenuManager.GUI.Serialization { public static class IconManager { /// /// Saves Icon to temporary file path. /// /// Icon to save. /// Shortcut Name /// Absolute file path of saved file. public static string SaveIcon(MagickImage icon, string shortcutName) { string websiteIconsFolder = GetWebsiteIconsFolder(); int fileNum = 0; while (File.Exists(Path.Combine(websiteIconsFolder, $"{shortcutName}_{fileNum}.ico"))) { fileNum++; } string iconPath = Path.Combine(websiteIconsFolder, $"{shortcutName}_{fileNum}.ico"); icon.Write(iconPath); return iconPath; } /// /// Removes all unused icons from the website icons folder. /// /// Shortcut Configuration. public static void ClearUnusedIcons(Config config) { List usedIcons = new List(); foreach (Shortcut shorctut in config.Shortcuts) { if (!string.IsNullOrEmpty(shorctut.IconPath)) { usedIcons.Add(shorctut.IconPath); } } // Get all files from directory. Delete those which arent in usedIcons string dir = GetWebsiteIconsFolder(); string[] filePaths = Directory.GetFiles(dir); foreach (string filePath in filePaths) { if (!filePath.EndsWith(".ico")) { return; } if (!usedIcons.Contains(filePath)) { File.Delete(filePath); } } } private static string GetWebsiteIconsFolder() { string baseDir = AppDomain.CurrentDomain.BaseDirectory; string folder = Path.Combine(baseDir, "Website Icons"); if (!Directory.Exists(folder)) { Directory.CreateDirectory(folder); } return folder; } } } ================================================ FILE: src/StartMenuManager.GUI/Serialization/JsonSerializer.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - © Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- using System; using System.IO; using Newtonsoft.Json; using StartMenuManager.Core.DataStructures; using StartMenuManager.Core.Serialization; namespace StartMenuManager.GUI.Serialization { public static class JsonSerializer { public static SettingsConfig GetSettings() { if (!File.Exists(GetSettingsFilePath())) { return SettingsConfig.GetDefaultSettings(); } StreamReader reader = new StreamReader(GetSettingsFilePath()); string contents = reader.ReadToEnd(); reader.Close(); return JsonConvert.DeserializeObject(contents); } public static void SaveSettings(SettingsConfig settings) { string settingsJson = JsonConvert.SerializeObject(settings, Formatting.Indented); StreamWriter writer = new StreamWriter(GetSettingsFilePath(), false); writer.WriteLine(settingsJson); writer.Close(); } public static string GetLastShortcutsJson() { if (!Directory.Exists(WindowRef.Wind.Settings.StartMenuFolder)) { return GetDefaultJson(); } if (!Directory.Exists(WindowRef.Wind.Settings.GetShortcutsFilePath())) { Directory.CreateDirectory(WindowRef.Wind.Settings.GetShortcutsFilePath()); } if (!File.Exists(WindowRef.Wind.Settings.GetShortcutsFilePath("shortcuts.json"))) { return GetDefaultJson(); } StreamReader reader = new StreamReader(WindowRef.Wind.Settings.GetShortcutsFilePath("shortcuts.json")); string contents = reader.ReadToEnd(); reader.Close(); return contents; } public static void SaveLastShortcutsJson(string jsonString) { if (!Directory.Exists(WindowRef.Wind.Settings.StartMenuFolder)) { return; } if (!Directory.Exists(WindowRef.Wind.Settings.GetShortcutsFilePath())) { Directory.CreateDirectory(WindowRef.Wind.Settings.GetShortcutsFilePath()); } StreamWriter writer = new StreamWriter(WindowRef.Wind.Settings.GetShortcutsFilePath("shortcuts.json"), false); writer.WriteLine(jsonString); writer.Close(); } private static string GetDefaultJson() { Config newConfig = new Config(); return Serializer.SerializeConfig(newConfig); } private static string GetSettingsFilePath() { return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "settings.json"); } } } ================================================ FILE: src/StartMenuManager.GUI/ShortcutControl.xaml ================================================  My Shortcut Test Shortcut Duplicate Shortcut Move Up Move Down Delete Shortcut Shortcut Type: Web File Folder Software Command Multi-Action Shortcut Name: Website Url: File Path: Folder Path: Software Path (e.g. .exe file): Command: Keep Terminal Open? Icon: None Selected. ================================================ FILE: src/StartMenuManager.GUI/ShortcutControl.xaml.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - © Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Windows; using System.Windows.Controls; using Microsoft.Win32; using StartMenuManager.Core.DataStructures; using StartMenuManager.Core.DataStructures.Actions; using StartMenuManager.GUI.Extensions; using StartMenuManager.GUI.Structures; namespace StartMenuManager.GUI { /// /// Interaction logic for ShortcutControl.xaml /// public partial class ShortcutControl : UserControl { private bool eventBlock = false; private Shortcut shortcut; public ShortcutControl(ShortcutType shortcutType) { InitializeComponent(); InitControl(shortcutType); } public ShortcutControl() { InitializeComponent(); InitControl(ShortcutType.Web); } public ShortcutType ShortcutType { get; set; } public List SubShorcuts { get; set; } public Shortcut Shortcut { get { if (ShortcutType == ShortcutType.Multi) { shortcut.Actions = new List(); if (SubShorcuts == null) { return shortcut; } foreach (SubShortcutControl subshort in SubShorcuts) { shortcut.Actions.Add(subshort.Shortcut.Actions[0]); } } return shortcut; } set { shortcut = value; } } private void InitControl(ShortcutType shortcutType) { ShortcutType = shortcutType; // Set up the underlying Shortcut class Shortcut = new Shortcut(); eventBlock = true; Shortcut.Name = "My Shortcut"; SetDefaultAction(); // Set up right UI: SetIcon(); InitUiBasedOnType(); SetFieldValuesFromShortcut(); eventBlock = false; } private void SetDefaultAction() { Shortcut.Actions.Clear(); switch (ShortcutType) { case ShortcutType.Web: Shortcut.Actions.Add(new WebsiteAction()); break; case ShortcutType.File: Shortcut.Actions.Add(new FileAction()); break; case ShortcutType.Folder: Shortcut.Actions.Add(new FolderAction()); break; case ShortcutType.Software: Shortcut.Actions.Add(new SoftwareAction()); break; case ShortcutType.Command: Shortcut.Actions.Add(new CommandAction()); break; } } ///////////////////////////////////////////////////////////////////////////////////////////// // Update UI from Shortcut class public void UpdateUi() { SetIcon(); InitUiBasedOnType(); SetFieldValuesFromShortcut(); } private void SetIcon() { switch (ShortcutType) { case ShortcutType.Web: Icon.Kind = MaterialDesignThemes.Wpf.PackIconKind.Web; break; case ShortcutType.File: Icon.Kind = MaterialDesignThemes.Wpf.PackIconKind.FileDocument; break; case ShortcutType.Folder: Icon.Kind = MaterialDesignThemes.Wpf.PackIconKind.Folder; break; case ShortcutType.Software: Icon.Kind = MaterialDesignThemes.Wpf.PackIconKind.Play; break; case ShortcutType.Command: Icon.Kind = MaterialDesignThemes.Wpf.PackIconKind.Terminal; break; case ShortcutType.Multi: Icon.Kind = MaterialDesignThemes.Wpf.PackIconKind.ClipboardList; break; } } private void InitUiBasedOnType() { WebsiteUi.Visibility = Visibility.Collapsed; FileUi.Visibility = Visibility.Collapsed; FolderUi.Visibility = Visibility.Collapsed; SoftwareUi.Visibility = Visibility.Collapsed; CommandUi.Visibility = Visibility.Collapsed; MultiUi.Visibility = Visibility.Collapsed; switch (ShortcutType) { case ShortcutType.Web: WebsiteUi.Visibility = Visibility.Visible; break; case ShortcutType.File: FileUi.Visibility = Visibility.Visible; break; case ShortcutType.Folder: FolderUi.Visibility = Visibility.Visible; break; case ShortcutType.Software: SoftwareUi.Visibility = Visibility.Visible; break; case ShortcutType.Command: CommandUi.Visibility = Visibility.Visible; break; case ShortcutType.Multi: MultiUi.Visibility = Visibility.Visible; break; } } private void SetFieldValuesFromShortcut() { eventBlock = true; ShortcutNameField.Text = Shortcut.Name; ShortcutTitleName.Text = Shortcut.Name; eventBlock = true; ShortcutTypeComboBox.SelectedIndex = (int)ShortcutType; if (!string.IsNullOrEmpty(Shortcut.IconPath)) { if (!File.Exists(Shortcut.IconPath)) { Shortcut.IconPath = string.Empty; ShotcutNameText.Text = "No icon selected."; } else { ShotcutNameText.Text = Path.GetFileName(Shortcut.IconPath); } } else { ShotcutNameText.Text = "No icon selected."; } switch (ShortcutType) { case ShortcutType.Web: WebsiteAction webaction = (WebsiteAction)Shortcut.Actions[0]; eventBlock = true; WebsiteUriField.Text = webaction.Url; eventBlock = true; break; case ShortcutType.File: FileAction fileAction = (FileAction)Shortcut.Actions[0]; eventBlock = true; FileUi_Path.Text = fileAction.Path; break; case ShortcutType.Folder: FolderAction folderAction = (FolderAction)Shortcut.Actions[0]; eventBlock = true; FolderUi_Path.Text = folderAction.Path; break; case ShortcutType.Software: SoftwareAction softwareAction = (SoftwareAction)Shortcut.Actions[0]; eventBlock = true; SoftwareUi_Path.Text = softwareAction.Path; break; case ShortcutType.Command: CommandAction comaction = (CommandAction)Shortcut.Actions[0]; eventBlock = true; CommandUi_Comand.Text = comaction.Command; eventBlock = true; CommandUi_KeepOpen.IsChecked = comaction.KeepOpen; break; case ShortcutType.Multi: break; } eventBlock = false; } public void CreateGroupActions(List actions) { SubShorcuts = new List(); if (actions != null) { foreach (Core.DataStructures.Action action in actions) { CreateSubShorcut(action, MultiUi_ShortcutsParent.Children.Count); } } } private SubShortcutControl CreateSubShorcut(Core.DataStructures.Action action, int index) { SubShortcutControl newControl = new SubShortcutControl(this); newControl.Shortcut.Actions[0] = action; newControl.ShortcutType = action.ToShortcutType(); MultiUi_ShortcutsParent.Children.Insert(index, newControl); SubShorcuts.Insert(index, newControl); newControl.UpdateUi(); return newControl; } ///////////////////////////////////////////////////////////////////////////////////////////// // Update Shortcut class from UI Events // Main changed events public void IconSelectedEvent(string filePath) { Shortcut.IconPath = filePath; ShotcutNameText.Text = Path.GetFileName(filePath); } private void ShortcutTypeChanged(object sender, SelectionChangedEventArgs e) { if (!eventBlock) { List oldActions = Shortcut.Actions.Select(a => a.Duplicate()).ToList(); ShortcutType oldType = ShortcutType; ShortcutType = (ShortcutType)ShortcutTypeComboBox.SelectedIndex; SetDefaultAction(); SetIcon(); InitUiBasedOnType(); SetFieldValuesFromShortcut(); if ((oldType != ShortcutType.Multi) && (ShortcutType == ShortcutType.Multi)) { MultiUi_ShortcutsParent.Children.Clear(); CreateGroupActions(new List() { oldActions[0] }); } if ((oldType == ShortcutType.Multi) && (ShortcutType != ShortcutType.Multi) && (oldActions.Count == 1)) { if (oldActions[0].ToShortcutType() == ShortcutType) { Shortcut.Actions[0] = oldActions[0]; SetFieldValuesFromShortcut(); } } } eventBlock = false; } private void ShortcutNameChanged(object sender, TextChangedEventArgs e) { if (!eventBlock) { Shortcut.Name = ShortcutNameField.Text; ShortcutTitleName.Text = Shortcut.Name; } eventBlock = false; } private void SelectIconFromFile(object sender, RoutedEventArgs e) { OpenFileDialog ofd = new OpenFileDialog(); ofd.Filter = "icon files (*.ico)|*.ico"; ofd.Title = "Select and Icon file to use for this Shortcut"; if (ofd.ShowDialog() == true) { if (File.Exists(ofd.FileName)) { Shortcut.IconPath = ofd.FileName; ShotcutNameText.Text = Path.GetFileName(ofd.FileName); } } } private void SelectIconFromWebsite(object sender, RoutedEventArgs e) { IconExtractorWindow.CreateOrFocusInstance((MainWindow)Application.Current.MainWindow, this); } private void ClearSelectedIcon(object sender, RoutedEventArgs e) { Shortcut.IconPath = string.Empty; ShotcutNameText.Text = "No icon selected."; } // Website action changed events private void WebsiteUriTextChanged(object sender, TextChangedEventArgs e) { if (!eventBlock) { WebsiteAction action = (WebsiteAction)Shortcut.Actions[0]; action.Url = WebsiteUriField.Text; } eventBlock = false; } // File action changed events private void FileUi_PathChanged(object sender, RoutedEventArgs e) { if (!eventBlock) { FileAction action = (FileAction)Shortcut.Actions[0]; action.Path = FileUi_Path.Text; } eventBlock = false; } private void FileUi_PathSelectPressed(object sender, RoutedEventArgs e) { OpenFileDialog openFileDialog = new OpenFileDialog(); openFileDialog.Filter = "All files (*.*)|*.*"; openFileDialog.InitialDirectory = Environment.SpecialFolder.Personal.ToString(); if (openFileDialog.ShowDialog() == true) { if (!string.IsNullOrEmpty(openFileDialog.FileName)) { FileAction action = (FileAction)Shortcut.Actions[0]; action.Path = openFileDialog.FileName; if (FileUi_Path.Text != openFileDialog.FileName) { eventBlock = true; FileUi_Path.Text = openFileDialog.FileName; } } } } // Folder action changed events private void FolderUi_PathChanged(object sender, RoutedEventArgs e) { if (!eventBlock) { FolderAction action = (FolderAction)Shortcut.Actions[0]; action.Path = FolderUi_Path.Text; } eventBlock = false; } private void FolderUi_PathSelectPressed(object sender, RoutedEventArgs e) { System.Windows.Forms.FolderBrowserDialog openFolderDialog = new System.Windows.Forms.FolderBrowserDialog(); openFolderDialog.Description = "Select the directory for the shortcut to open."; System.Windows.Forms.DialogResult result = openFolderDialog.ShowDialog(); if (result == System.Windows.Forms.DialogResult.OK) { if (!string.IsNullOrEmpty(openFolderDialog.SelectedPath)) { FolderAction action = (FolderAction)Shortcut.Actions[0]; action.Path = openFolderDialog.SelectedPath; if (FolderUi_Path.Text != openFolderDialog.SelectedPath) { eventBlock = true; FolderUi_Path.Text = openFolderDialog.SelectedPath; } } } } // Software action changed evetns private void SoftwareUi_PathChanged(object sender, RoutedEventArgs e) { if (!eventBlock) { SoftwareAction action = (SoftwareAction)Shortcut.Actions[0]; action.Path = SoftwareUi_Path.Text; } eventBlock = false; } private void SoftwareUi_PathSelectPressed(object sender, RoutedEventArgs e) { OpenFileDialog openFileDialog = new OpenFileDialog(); openFileDialog.Filter = "Exe Files (*.exe)|*.exe|All files (*.*)|*.*"; openFileDialog.InitialDirectory = Environment.SpecialFolder.ProgramFiles.ToString(); if (openFileDialog.ShowDialog() == true) { if (!string.IsNullOrEmpty(openFileDialog.FileName)) { SoftwareAction action = (SoftwareAction)Shortcut.Actions[0]; action.Path = openFileDialog.FileName; if (SoftwareUi_Path.Text != openFileDialog.FileName) { eventBlock = true; SoftwareUi_Path.Text = openFileDialog.FileName; } } } } // Command action changed events private void CommandUi_CommandTextChanged(object sender, RoutedEventArgs e) { if (!eventBlock) { CommandAction action = (CommandAction)Shortcut.Actions[0]; action.Command = CommandUi_Comand.Text; } eventBlock = false; } private void CommandUi_KeepOpen_Checked(object sender, RoutedEventArgs e) { if (!eventBlock) { CommandAction action = (CommandAction)Shortcut.Actions[0]; action.KeepOpen = true; } eventBlock = false; } private void CommandUi_KeepOpen_Unchecked(object sender, RoutedEventArgs e) { if (!eventBlock) { CommandAction action = (CommandAction)Shortcut.Actions[0]; action.KeepOpen = false; } eventBlock = false; } // Multi shortcut changed events private void MultiUi_AddShorcutButtonPressed(object sender, RoutedEventArgs e) { if (SubShorcuts == null) { SubShorcuts = new List(); } SubShortcutControl newControl = new SubShortcutControl(this); MultiUi_ShortcutsParent.Children.Add(newControl); SubShorcuts.Add(newControl); } public void DuplicateChild(SubShortcutControl control) { int insertIndex = SubShorcuts.IndexOf(control) + 1; Shortcut newShortcut = control.Shortcut.Duplicate(); SubShortcutControl newControl = CreateSubShorcut(newShortcut.Actions[0], insertIndex); } public void MoveUpChild(SubShortcutControl control) { int oldIndex = SubShorcuts.IndexOf(control); if (oldIndex > 0) { SubShorcuts.Remove(control); MultiUi_ShortcutsParent.Children.Remove(control); SubShorcuts.Insert(oldIndex - 1, control); MultiUi_ShortcutsParent.Children.Insert(oldIndex - 1, control); } } public void MoveDownChild(SubShortcutControl control) { int oldIndex = SubShorcuts.IndexOf(control); if (oldIndex < SubShorcuts.Count - 1) { SubShorcuts.Remove(control); MultiUi_ShortcutsParent.Children.Remove(control); SubShorcuts.Insert(oldIndex + 1, control); MultiUi_ShortcutsParent.Children.Insert(oldIndex + 1, control); } } public void DeleteChild(SubShortcutControl control) { if (WindowRef.Wind.Settings.YesNoDialogsEnabled) { Dialogs.YesNoDialog.SetMessage("Are you sure?", $"Do you want to remove the action?", "Yes", "No", (isYes) => RemoveSubShortcutYes(isYes, control)); DialogManager.Show(Structures.DialogTypes.YesNoDialog); } else { RemoveSubShortcutYes(true, control); } } private void RemoveSubShortcutYes(bool isYes, SubShortcutControl control) { if (isYes) { SubShorcuts.Remove(control); MultiUi_ShortcutsParent.Children.Remove(control); } } ///////////////////////////////////////////////////////////////////////////////////////////// // Other Events private void DeleteShortcutButtonClick(object sender, RoutedEventArgs e) { DeleteShortcut(); } public void MenuComboBoxSelectionChanged(object sender, SelectionChangedEventArgs e) { switch (MenuComboBox.SelectedIndex) { case 0: TestRunShortcut(); break; case 1: DuplicateShortcut(); break; case 2: MoveUpShortcut(); break; case 3: MoveDownShortcut(); break; case 4: DeleteShortcut(); break; } MenuComboBox.SelectedIndex = -1; } private void TestRunShortcut() { ShortcutListArea.TestRunShortcut(Shortcut); } private void DuplicateShortcut() { ShortcutListArea.DuplicateShortcut(this); } private void MoveUpShortcut() { ShortcutListArea.MoveUpShortcut(this); } private void MoveDownShortcut() { ShortcutListArea.MoveDownShortcut(this); } private void DeleteShortcut() { ShortcutListArea.RemoveShortcut(this); } } } ================================================ FILE: src/StartMenuManager.GUI/ShortcutListArea.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - © Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- using System.Collections.Generic; using System.IO; using System.Windows; using StartMenuManager.Core.DataStructures; using StartMenuManager.Core.Serialization; using StartMenuManager.GUI.Extensions; using static StartMenuManager.GUI.WindowRef; namespace StartMenuManager.GUI { public static class ShortcutListArea { public static List Shortcuts { get; set; } = new List { }; public static void InitEvents() { Wind.ShortcutListArea_AddButton.Click += (sender, args) => AddShortcut(sender, args); } public static void AddShortcut(object sender, RoutedEventArgs args) { ShortcutControl newControl = new ShortcutControl(); Wind.ShortcutListArea_ShortcutsParent.Children.Add(newControl); Shortcuts.Add(newControl); } private static ShortcutControl AddShortcut(Shortcut shortcut) { return AddShortcut(shortcut, Shortcuts.Count); } private static ShortcutControl AddShortcut(Shortcut shortcut, int insertIndex) { ShortcutControl newControl = new ShortcutControl(); newControl.Shortcut = shortcut; if (shortcut.Actions == null) { shortcut.Actions = new List(); } if (shortcut.Actions.Count != 1) { newControl.ShortcutType = Structures.ShortcutType.Multi; newControl.CreateGroupActions(shortcut.Actions); } else { newControl.ShortcutType = shortcut.Actions[0].ToShortcutType(); } Wind.ShortcutListArea_ShortcutsParent.Children.Insert(insertIndex, newControl); Shortcuts.Insert(insertIndex, newControl); newControl.UpdateUi(); return newControl; } private static bool IsFolder(string path) { FileAttributes attr = File.GetAttributes(path); if ((attr & FileAttributes.Directory) == FileAttributes.Directory) { return true; } return false; } public static void RemoveShortcut(ShortcutControl control) { if (Wind.Settings.YesNoDialogsEnabled) { Dialogs.YesNoDialog.SetMessage("Are you sure?", $"Do you want to remove the shortcut \"{control.Shortcut.Name}\"?", "Yes", "No", (isYes) => RemoveShortcutYes(isYes, control)); DialogManager.Show(Structures.DialogTypes.YesNoDialog); } else { RemoveShortcutYes(true, control); } } private static void RemoveShortcutYes(bool isYes, ShortcutControl control) { if (isYes) { Shortcuts.Remove(control); Wind.ShortcutListArea_ShortcutsParent.Children.Remove(control); } } public static void RemoveAllShortcuts() { Shortcuts.Clear(); Wind.ShortcutListArea_ShortcutsParent.Children.Clear(); } public static void LoadShortcuts(List shortcuts) { RemoveAllShortcuts(); if (shortcuts == null) { return; } foreach (Shortcut s in shortcuts) { AddShortcut(s); } } public static Config GetConfig() { Config newConfig = new Config(); newConfig.Shortcuts = new List(); foreach (ShortcutControl shortcutControl in Shortcuts) { newConfig.Shortcuts.Add(shortcutControl.Shortcut); } return newConfig; } public static void TestRunShortcut(Shortcut shortcut, bool isSub = false) { // Validate the shortcut (individually) first ValidationError err = shortcut.IsValid(); if (err != null) { Wind.ValiationError.Visibility = Visibility.Visible; Wind.ValidationErrorText.Text = isSub ? $"Error: {err.Error}" : $"Error: \"{err.Shortcut.Name}\" {err.Error}"; return; } else { Wind.ValiationError.Visibility = Visibility.Collapsed; } string tempShortcutJsonPath = Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "Runner", "temp,json"); string shortcutJson = Serializer.SerializeShortcut(shortcut); StreamWriter writer = new StreamWriter(tempShortcutJsonPath, false); writer.Write(shortcutJson); writer.Close(); StartMenuManager.GUI.Runner.Run(tempShortcutJsonPath); } public static void DuplicateShortcut(ShortcutControl control) { int insertIndex = Shortcuts.IndexOf(control) + 1; Shortcut newShortcut = control.Shortcut.Duplicate(); ShortcutControl newControl = AddShortcut(newShortcut, insertIndex); } public static void MoveUpShortcut(ShortcutControl control) { int oldIndex = Shortcuts.IndexOf(control); if (oldIndex > 0) { Shortcuts.Remove(control); Wind.ShortcutListArea_ShortcutsParent.Children.Remove(control); Shortcuts.Insert(oldIndex - 1, control); Wind.ShortcutListArea_ShortcutsParent.Children.Insert(oldIndex - 1, control); } } public static void MoveDownShortcut(ShortcutControl control) { int oldIndex = Shortcuts.IndexOf(control); if (oldIndex < Shortcuts.Count - 1) { Shortcuts.Remove(control); Wind.ShortcutListArea_ShortcutsParent.Children.Remove(control); Shortcuts.Insert(oldIndex + 1, control); Wind.ShortcutListArea_ShortcutsParent.Children.Insert(oldIndex + 1, control); } } } } ================================================ FILE: src/StartMenuManager.GUI/StartMenuManager.GUI.csproj ================================================  Debug AnyCPU {AB31D486-50B4-4FF1-9E2C-3D8A29FB8EF4} WinExe StartMenuManager.GUI Start Menu Manager v4.7.2 512 {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 4 true true AnyCPU true full false bin\Debug\ DEBUG;TRACE prompt 4 AnyCPU pdbonly true bin\Release\ TRACE prompt 4 icon-256.ico app.manifest 4.0 MSBuild:Compile Designer IconExtractorWindow.xaml SubShortcutControl.xaml ShortcutControl.xaml Designer MSBuild:Compile MSBuild:Compile Designer App.xaml Code MainWindow.xaml Code Designer MSBuild:Compile Designer MSBuild:Compile Code True True Resources.resx True Settings.settings True ResXFileCodeGenerator Resources.Designer.cs SettingsSingleFileGenerator Settings.Designer.cs {9B9FF48A-D1F7-47D5-8E22-892DAD1FF4A5} HL {f027fcb2-cc37-4d24-a2ab-072e19b87a18} StartMenuManager.Core {3e22a174-15f9-4c62-a15c-3b5e5e3f12bf} TextEditLib 4.7.0.9 3.1.3 1.0.2 ================================================ FILE: src/StartMenuManager.GUI/Structures/DialogTypes.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - © Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- namespace StartMenuManager.GUI.Structures { public enum DialogTypes { SettingsDialog, MessageDialog, YesNoDialog, } } ================================================ FILE: src/StartMenuManager.GUI/Structures/ShortcutType.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - © Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- namespace StartMenuManager.GUI.Structures { public enum ShortcutType { Web, File, Folder, Software, Command, Multi, } } ================================================ FILE: src/StartMenuManager.GUI/SubShortcutControl.xaml ================================================  My Shortcut Test Shortcut Duplicate Shortcut Move Up Move Down Delete Shortcut Shortcut Type: Web File Folder Software Command Website Url: File Path: Folder Path: Software Path (e.g. .exe file): Command: Keep Terminal Open? ================================================ FILE: src/StartMenuManager.GUI/SubShortcutControl.xaml.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - © Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- using System; using System.Windows; using System.Windows.Controls; using Microsoft.Win32; using StartMenuManager.Core.DataStructures; using StartMenuManager.Core.DataStructures.Actions; using StartMenuManager.GUI.Structures; namespace StartMenuManager.GUI { /// /// Interaction logic for ShortcutControl.xaml /// public partial class SubShortcutControl : UserControl { private bool eventBlock = false; private ShortcutControl parent; public SubShortcutControl(ShortcutControl parentControl) { parent = parentControl; InitializeComponent(); InitControl(ShortcutType.Web); } public ShortcutType ShortcutType { get; set; } public Shortcut Shortcut { get; set; } private void InitControl(ShortcutType shortcutType) { ShortcutType = shortcutType; // Set up the underlying Shortcut class Shortcut = new Shortcut(); eventBlock = true; Shortcut.Name = "My Shortcut"; SetDefaultAction(); // Set up right UI: SetIcon(); InitUiBasedOnType(); SetFieldValuesFromShortcut(); eventBlock = false; } private void SetDefaultAction() { Shortcut.Actions.Clear(); switch (ShortcutType) { case ShortcutType.Web: Shortcut.Actions.Add(new WebsiteAction()); break; case ShortcutType.File: Shortcut.Actions.Add(new FileAction()); break; case ShortcutType.Folder: Shortcut.Actions.Add(new FolderAction()); break; case ShortcutType.Software: Shortcut.Actions.Add(new SoftwareAction()); break; case ShortcutType.Command: Shortcut.Actions.Add(new CommandAction()); break; } } ///////////////////////////////////////////////////////////////////////////////////////////// // Update UI from Shortcut class public void UpdateUi() { SetIcon(); InitUiBasedOnType(); SetFieldValuesFromShortcut(); } private void SetIcon() { switch (ShortcutType) { case ShortcutType.Web: Icon.Kind = MaterialDesignThemes.Wpf.PackIconKind.Web; break; case ShortcutType.File: Icon.Kind = MaterialDesignThemes.Wpf.PackIconKind.FileDocument; break; case ShortcutType.Folder: Icon.Kind = MaterialDesignThemes.Wpf.PackIconKind.Folder; break; case ShortcutType.Software: Icon.Kind = MaterialDesignThemes.Wpf.PackIconKind.Play; break; case ShortcutType.Command: Icon.Kind = MaterialDesignThemes.Wpf.PackIconKind.Terminal; break; } } private void InitUiBasedOnType() { WebsiteUi.Visibility = Visibility.Collapsed; FileUi.Visibility = Visibility.Collapsed; FolderUi.Visibility = Visibility.Collapsed; SoftwareUi.Visibility = Visibility.Collapsed; CommandUi.Visibility = Visibility.Collapsed; switch (ShortcutType) { case ShortcutType.Web: WebsiteUi.Visibility = Visibility.Visible; break; case ShortcutType.File: FileUi.Visibility = Visibility.Visible; break; case ShortcutType.Folder: FolderUi.Visibility = Visibility.Visible; break; case ShortcutType.Software: SoftwareUi.Visibility = Visibility.Visible; break; case ShortcutType.Command: CommandUi.Visibility = Visibility.Visible; break; } } private void SetFieldValuesFromShortcut() { eventBlock = true; ShortcutTitleName.Text = $"{Enum.GetName(typeof(ShortcutType), ShortcutType)} Action"; eventBlock = true; ShortcutTypeComboBox.SelectedIndex = (int)ShortcutType; switch (ShortcutType) { case ShortcutType.Web: WebsiteAction webaction = (WebsiteAction)Shortcut.Actions[0]; eventBlock = true; WebsiteUriField.Text = webaction.Url; eventBlock = true; break; case ShortcutType.File: FileAction fileAction = (FileAction)Shortcut.Actions[0]; eventBlock = true; FileUi_Path.Text = fileAction.Path; break; case ShortcutType.Folder: FolderAction folderAction = (FolderAction)Shortcut.Actions[0]; eventBlock = true; FolderUi_Path.Text = folderAction.Path; break; case ShortcutType.Software: SoftwareAction softwareAction = (SoftwareAction)Shortcut.Actions[0]; eventBlock = true; SoftwareUi_Path.Text = softwareAction.Path; break; case ShortcutType.Command: CommandAction comaction = (CommandAction)Shortcut.Actions[0]; eventBlock = true; CommandUi_Comand.Text = comaction.Command; eventBlock = true; CommandUi_KeepOpen.IsChecked = comaction.KeepOpen; break; } eventBlock = false; } ///////////////////////////////////////////////////////////////////////////////////////////// // Update Shortcut class from UI Events // Main changed events private void ShortcutTypeChanged(object sender, SelectionChangedEventArgs e) { if (!eventBlock) { ShortcutType = (ShortcutType)ShortcutTypeComboBox.SelectedIndex; SetDefaultAction(); SetIcon(); InitUiBasedOnType(); SetFieldValuesFromShortcut(); } eventBlock = false; } // Website action changed events private void WebsiteUriTextChanged(object sender, TextChangedEventArgs e) { if (!eventBlock) { WebsiteAction action = (WebsiteAction)Shortcut.Actions[0]; action.Url = WebsiteUriField.Text; } eventBlock = false; } // File action changed events private void FileUi_PathChanged(object sender, RoutedEventArgs e) { if (!eventBlock) { FileAction action = (FileAction)Shortcut.Actions[0]; action.Path = FileUi_Path.Text; } eventBlock = false; } private void FileUi_PathSelectPressed(object sender, RoutedEventArgs e) { OpenFileDialog openFileDialog = new OpenFileDialog(); openFileDialog.Filter = "All files (*.*)|*.*"; openFileDialog.InitialDirectory = Environment.SpecialFolder.Personal.ToString(); if (openFileDialog.ShowDialog() == true) { if (!string.IsNullOrEmpty(openFileDialog.FileName)) { FileAction action = (FileAction)Shortcut.Actions[0]; action.Path = openFileDialog.FileName; if (FileUi_Path.Text != openFileDialog.FileName) { eventBlock = true; FileUi_Path.Text = openFileDialog.FileName; } } } } // Folder action changed events private void FolderUi_PathChanged(object sender, RoutedEventArgs e) { if (!eventBlock) { FolderAction action = (FolderAction)Shortcut.Actions[0]; action.Path = FolderUi_Path.Text; } eventBlock = false; } private void FolderUi_PathSelectPressed(object sender, RoutedEventArgs e) { System.Windows.Forms.FolderBrowserDialog openFolderDialog = new System.Windows.Forms.FolderBrowserDialog(); openFolderDialog.Description = "Select the directory for the shortcut to open."; System.Windows.Forms.DialogResult result = openFolderDialog.ShowDialog(); if (result == System.Windows.Forms.DialogResult.OK) { if (!string.IsNullOrEmpty(openFolderDialog.SelectedPath)) { FolderAction action = (FolderAction)Shortcut.Actions[0]; action.Path = openFolderDialog.SelectedPath; if (FolderUi_Path.Text != openFolderDialog.SelectedPath) { eventBlock = true; FolderUi_Path.Text = openFolderDialog.SelectedPath; } } } } // Software action changed evetns private void SoftwareUi_PathChanged(object sender, RoutedEventArgs e) { if (!eventBlock) { SoftwareAction action = (SoftwareAction)Shortcut.Actions[0]; action.Path = SoftwareUi_Path.Text; } eventBlock = false; } private void SoftwareUi_PathSelectPressed(object sender, RoutedEventArgs e) { OpenFileDialog openFileDialog = new OpenFileDialog(); openFileDialog.Filter = "Exe Files (*.exe)|*.exe|All files (*.*)|*.*"; openFileDialog.InitialDirectory = Environment.SpecialFolder.ProgramFiles.ToString(); if (openFileDialog.ShowDialog() == true) { if (!string.IsNullOrEmpty(openFileDialog.FileName)) { SoftwareAction action = (SoftwareAction)Shortcut.Actions[0]; action.Path = openFileDialog.FileName; if (SoftwareUi_Path.Text != openFileDialog.FileName) { eventBlock = true; SoftwareUi_Path.Text = openFileDialog.FileName; } } } } // Command action changed events private void CommandUi_CommandTextChanged(object sender, RoutedEventArgs e) { if (!eventBlock) { CommandAction action = (CommandAction)Shortcut.Actions[0]; action.Command = CommandUi_Comand.Text; } eventBlock = false; } private void CommandUi_KeepOpen_Checked(object sender, RoutedEventArgs e) { if (!eventBlock) { CommandAction action = (CommandAction)Shortcut.Actions[0]; action.KeepOpen = true; } eventBlock = false; } private void CommandUi_KeepOpen_Unchecked(object sender, RoutedEventArgs e) { if (!eventBlock) { CommandAction action = (CommandAction)Shortcut.Actions[0]; action.KeepOpen = false; } eventBlock = false; } ///////////////////////////////////////////////////////////////////////////////////////////// // Other Events private void DeleteShortcutButtonClick(object sender, RoutedEventArgs e) { DeleteShortcut(); } public void MenuComboBoxSelectionChanged(object sender, SelectionChangedEventArgs e) { switch (MenuComboBox.SelectedIndex) { case 0: TestRunShortcut(); break; case 1: DuplicateShortcut(); break; case 2: MoveUpShortcut(); break; case 3: MoveDownShortcut(); break; case 4: DeleteShortcut(); break; } MenuComboBox.SelectedIndex = -1; } private void TestRunShortcut() { ShortcutListArea.TestRunShortcut(Shortcut, true); } private void DuplicateShortcut() { parent.DuplicateChild(this); } private void MoveUpShortcut() { parent.MoveUpChild(this); } private void MoveDownShortcut() { parent.MoveDownChild(this); } private void DeleteShortcut() { parent.DeleteChild(this); } } } ================================================ FILE: src/StartMenuManager.GUI/TitleBarButtons.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - © Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- using System; using System.Windows; using StartMenuManager.Core.DataStructures; using StartMenuManager.Core.Serialization; using static StartMenuManager.GUI.WindowRef; namespace StartMenuManager.GUI { public static class TitleBarButtons { private static bool inJsonView = false; public static void InitEvents() { Wind.TitleBar_SettingsButton.Click += (sender, args) => SettingsButtonPressed(sender, args); Wind.TitleBar_JsonButton.Click += (sender, args) => JsonButtonPressed(sender, args); } public static void SettingsButtonPressed(object sender, RoutedEventArgs args) { if (DialogManager.OpenDialogSession != null) { return; } DialogManager.Show(Structures.DialogTypes.SettingsDialog); } public static void JsonButtonPressed(object sender, RoutedEventArgs args) { if (DialogManager.OpenDialogSession != null) { return; } if (inJsonView) { // Attempt to Deserialize Json string json = Wind.textEditor.Text; Config config = null; try { config = Serializer.DeserializeConfig(json); } catch (Exception e) { Dialogs.MessageDialog.SetMessage("Json Error", e.Message); DialogManager.Show(Structures.DialogTypes.MessageDialog); return; } ShortcutListArea.LoadShortcuts(config.Shortcuts); Wind.JsonView.Visibility = Visibility.Collapsed; Wind.NonJsonView.Visibility = Visibility.Visible; Wind.ValiationError.Visibility = Visibility.Collapsed; } else { LoadJsonFromShortcuts(); Wind.JsonView.Visibility = Visibility.Visible; Wind.NonJsonView.Visibility = Visibility.Collapsed; } inJsonView = !inJsonView; } private static void LoadJsonFromShortcuts() { Config config = ShortcutListArea.GetConfig(); string configJson = Serializer.SerializeConfig(config); JsonViewManager.SetJson(configJson); } } } ================================================ FILE: src/StartMenuManager.GUI/Utils/DialogManager.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - © Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- using System; using MaterialDesignThemes.Wpf; using StartMenuManager.GUI.Dialogs; using static StartMenuManager.GUI.WindowRef; namespace StartMenuManager.GUI { public static class DialogManager { public static DialogSession OpenDialogSession { get; set; } /// /// Opens a dialog /// /// The type of dialog to open public static async void Show(Structures.DialogTypes dialogType) { Wind.SettingsDialog.Visibility = System.Windows.Visibility.Collapsed; Wind.MessageDialog.Visibility = System.Windows.Visibility.Collapsed; Wind.YesNoDialog.Visibility = System.Windows.Visibility.Collapsed; switch (dialogType) { case Structures.DialogTypes.SettingsDialog: SettingsDialog.InitDialog(); Wind.SettingsDialog.Visibility = System.Windows.Visibility.Visible; break; case Structures.DialogTypes.MessageDialog: Wind.MessageDialog.Visibility = System.Windows.Visibility.Visible; break; case Structures.DialogTypes.YesNoDialog: Wind.YesNoDialog.Visibility = System.Windows.Visibility.Visible; break; } try { var result = await Wind.dialogHost.ShowDialog( Wind.DialogContent, delegate(object send, DialogOpenedEventArgs args) { DialogManager.OpenDialogSession = args.Session; }); } catch (InvalidOperationException) { } } } } ================================================ FILE: src/StartMenuManager.GUI/Utils/IconExtractorWindow_TitleBarControl.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - © Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- using System; using System.Runtime.InteropServices; using System.Windows; using System.Windows.Forms; using System.Windows.Input; namespace StartMenuManager.GUI { public static class IconExtractorWindow_TitleBarControl { private static Point startPos; private static Screen[] screens = System.Windows.Forms.Screen.AllScreens; public static void InitEvents(IconExtractorWindow wind) { wind.TitleBar_MaximizeButton.Click += (sender, e) => Maximize_Click(wind, sender, e); wind.TitleBar_CloseButton.Click += (sender, e) => Close_Click(wind, sender, e); wind.TitleBarArea.PreviewMouseDown += (sender, e) => System_MouseDown(wind, sender, e); wind.TitleBarArea.PreviewMouseMove += (sender, e) => System_MouseMove(wind, sender, e); wind.LocationChanged += (sender, e) => Window_LocationChanged(wind, sender, e); wind.StateChanged += (sender, e) => Window_StateChanged(wind, sender, e); } private static void Window_LocationChanged(IconExtractorWindow wind, object sender, EventArgs e) { int sum = 0; foreach (var item in screens) { sum += item.WorkingArea.Width; if (sum >= wind.Left + (wind.Width / 2)) { wind.MaxHeight = item.WorkingArea.Height + 7; break; } } } private static void System_MouseDown(IconExtractorWindow wind, object sender, MouseButtonEventArgs e) { if (e.ChangedButton == MouseButton.Left) { if (e.ClickCount >= 2) { wind.WindowState = (wind.WindowState == WindowState.Normal) ? WindowState.Maximized : WindowState.Normal; } else { startPos = e.GetPosition(null); } } else if (e.ChangedButton == MouseButton.Right) { var pos = wind.PointToScreen(e.GetPosition(wind)); IntPtr hWnd = new System.Windows.Interop.WindowInteropHelper(wind).Handle; IntPtr hMenu = GetSystemMenu(hWnd, false); int cmd = TrackPopupMenu(hMenu, 0x100, (int)pos.X, (int)pos.Y, 0, hWnd, IntPtr.Zero); if (cmd > 0) { SendMessage(hWnd, 0x112, (IntPtr)cmd, IntPtr.Zero); } } } [DllImport("user32.dll")] public static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp); [DllImport("user32.dll")] public static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert); [DllImport("user32.dll")] public static extern int TrackPopupMenu(IntPtr hMenu, uint uFlags, int x, int y, int nReserved, IntPtr hWnd, IntPtr prcRect); private static void System_MouseMove(IconExtractorWindow wind, object sender, System.Windows.Input.MouseEventArgs e) { if (e.LeftButton == MouseButtonState.Pressed) { if (wind.WindowState == WindowState.Maximized && Math.Abs(startPos.Y - e.GetPosition(null).Y) > 2) { var point = wind.PointToScreen(e.GetPosition(null)); wind.WindowState = WindowState.Normal; wind.Left = point.X - (wind.ActualWidth / 2); wind.Top = point.Y - (wind.border.ActualHeight / 2); } wind.DragMove(); } } private static void Maximize_Click(IconExtractorWindow wind, object sender, RoutedEventArgs e) { wind.WindowState = (wind.WindowState == WindowState.Normal) ? WindowState.Maximized : WindowState.Normal; } private static void Close_Click(IconExtractorWindow wind, object sender, RoutedEventArgs e) { wind.Close(); } private static void Mimimize_Click(IconExtractorWindow wind, object sender, RoutedEventArgs e) { wind.WindowState = WindowState.Minimized; } private static void Window_StateChanged(IconExtractorWindow wind, object sender, EventArgs e) { if (wind.WindowState == WindowState.Maximized) { wind.main.BorderThickness = new Thickness(0); wind.main.Margin = new Thickness(7, 7, 7, 0); wind.rectMax.Visibility = Visibility.Hidden; wind.rectMin.Visibility = Visibility.Visible; } else { wind.main.BorderThickness = new Thickness(1); wind.main.Margin = new Thickness(0); wind.rectMax.Visibility = Visibility.Visible; wind.rectMin.Visibility = Visibility.Hidden; } } } } ================================================ FILE: src/StartMenuManager.GUI/Utils/ThemeManager.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - © Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- using System.Windows; using System.Windows.Media; using HL.Interfaces; using HL.Manager; using MaterialDesignThemes.Wpf; using static StartMenuManager.GUI.WindowRef; namespace StartMenuManager.GUI { public class ThemeManager { private static readonly PaletteHelper _paletteHelper = new PaletteHelper(); public static void InitTheme() { switch (Wind.Settings.Theme) { case "light": SetLightTheme(); break; case "dark": SetDarkTheme(); break; default: SetSystemTheme(); break; } } public static void SetSystemTheme() { if (IsSystemLightMode()) { SetLightTheme(); } else { SetDarkTheme(); } } public static void SetDarkTheme() { ITheme theme = _paletteHelper.GetTheme(); IBaseTheme baseTheme = new MaterialDesignDarkTheme(); theme.SetBaseTheme(baseTheme); theme.SetPrimaryColor((Color)ColorConverter.ConvertFromString("#243b45")); theme.SetSecondaryColor((Color)ColorConverter.ConvertFromString("#3d6475")); _paletteHelper.SetTheme(theme); SetAvalonTheme(true); } public static void SetLightTheme() { ITheme theme = _paletteHelper.GetTheme(); IBaseTheme baseTheme = new MaterialDesignLightTheme(); theme.SetBaseTheme(baseTheme); theme.SetPrimaryColor((Color)ColorConverter.ConvertFromString("#7dd8ff")); theme.SetSecondaryColor((Color)ColorConverter.ConvertFromString("#b0e7ff")); _paletteHelper.SetTheme(theme); SetAvalonTheme(false); } private static bool IsSystemLightMode() { bool isLightMode = false; try { var v = Microsoft.Win32.Registry.GetValue(@"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize", "AppsUseLightTheme", "1"); if (v != null && v.ToString() == "1") { isLightMode = true; } } catch { } return isLightMode; } private static void SetAvalonTheme(bool isDark) { IThemedHighlightingManager hm = ThemedHighlightingManager.Instance; hm.SetCurrentTheme(isDark ? "VS2019_Dark" : "Light"); MainWindow window = (MainWindow)Application.Current.MainWindow; window.textEditor.SyntaxHighlighting = hm.GetDefinitionByExtension(".js"); window.textEditor.Background = new SolidColorBrush(isDark ? Color.FromRgb(30, 30, 30) : Color.FromRgb(255, 255, 255)); window.textEditor.Foreground = new SolidColorBrush(isDark ? Color.FromRgb(255, 255, 255) : Color.FromRgb(0, 0, 0)); window.textEditor.LineNumbersForeground = new SolidColorBrush(isDark ? Color.FromRgb(190, 190, 190) : Color.FromRgb(60, 60, 60)); window.textEditor.EditorCurrentLineBackground = new SolidColorBrush(isDark ? Color.FromRgb(37, 37, 37) : Color.FromRgb(245, 245, 245)); } } } ================================================ FILE: src/StartMenuManager.GUI/Utils/TitleBarControl.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - © Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- using System; using System.Runtime.InteropServices; using System.Windows; using System.Windows.Forms; using System.Windows.Input; using StartMenuManager.GUI.Dialogs; using static StartMenuManager.GUI.WindowRef; namespace StartMenuManager.GUI { public static class TitleBarControl { private static Point startPos; private static Screen[] screens = System.Windows.Forms.Screen.AllScreens; public static void InitEvents() { Wind.TitleBar_MinimizeButton.Click += (sender, e) => Mimimize_Click(sender, e); Wind.TitleBar_MaximizeButton.Click += (sender, e) => Maximize_Click(sender, e); Wind.TitleBar_CloseButton.Click += (sender, e) => Close_Click(sender, e); Wind.TitleBarArea.PreviewMouseDown += (sender, e) => System_MouseDown(sender, e); Wind.TitleBarArea.PreviewMouseMove += (sender, e) => System_MouseMove(sender, e); Wind.LocationChanged += (sender, e) => Window_LocationChanged(sender, e); Wind.StateChanged += (sender, e) => Window_StateChanged(sender, e); } private static void Window_LocationChanged(object sender, EventArgs e) { int sum = 0; foreach (var item in screens) { sum += item.WorkingArea.Width; if (sum >= Wind.Left + (Wind.Width / 2)) { Wind.MaxHeight = item.WorkingArea.Height + 7; break; } } } private static void System_MouseDown(object sender, MouseButtonEventArgs e) { if (e.ChangedButton == MouseButton.Left) { if (e.ClickCount >= 2) { Wind.WindowState = (Wind.WindowState == WindowState.Normal) ? WindowState.Maximized : WindowState.Normal; } else { startPos = e.GetPosition(null); } } else if (e.ChangedButton == MouseButton.Right) { var pos = Wind.PointToScreen(e.GetPosition(Wind)); IntPtr hWnd = new System.Windows.Interop.WindowInteropHelper(Wind).Handle; IntPtr hMenu = GetSystemMenu(hWnd, false); int cmd = TrackPopupMenu(hMenu, 0x100, (int)pos.X, (int)pos.Y, 0, hWnd, IntPtr.Zero); if (cmd > 0) { SendMessage(hWnd, 0x112, (IntPtr)cmd, IntPtr.Zero); } } } [DllImport("user32.dll")] public static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp); [DllImport("user32.dll")] public static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert); [DllImport("user32.dll")] public static extern int TrackPopupMenu(IntPtr hMenu, uint uFlags, int x, int y, int nReserved, IntPtr hWnd, IntPtr prcRect); private static void System_MouseMove(object sender, System.Windows.Input.MouseEventArgs e) { if (e.LeftButton == MouseButtonState.Pressed) { if (Wind.WindowState == WindowState.Maximized && Math.Abs(startPos.Y - e.GetPosition(null).Y) > 2) { var point = Wind.PointToScreen(e.GetPosition(null)); Wind.WindowState = WindowState.Normal; Wind.Left = point.X - (Wind.ActualWidth / 2); Wind.Top = point.Y - (Wind.border.ActualHeight / 2); } Wind.DragMove(); } } private static void Maximize_Click(object sender, RoutedEventArgs e) { Wind.WindowState = (Wind.WindowState == WindowState.Normal) ? WindowState.Maximized : WindowState.Normal; } private static void Close_Click(object sender, RoutedEventArgs e) { if (Wind.Settings.YesNoDialogsEnabled) { YesNoDialog.SetMessage("Are you sure you want to quit?", "You will loose any changes.", "Yes", "No", CloseComplete); DialogManager.Show(Structures.DialogTypes.YesNoDialog); } else { CloseComplete(true); } } private static void CloseComplete(bool shouldClose) { if (shouldClose) { Wind.Close(); } } private static void Mimimize_Click(object sender, RoutedEventArgs e) { Wind.WindowState = WindowState.Minimized; } private static void Window_StateChanged(object sender, EventArgs e) { if (Wind.WindowState == WindowState.Maximized) { Wind.main.BorderThickness = new Thickness(0); Wind.main.Margin = new Thickness(7, 7, 7, 0); Wind.rectMax.Visibility = Visibility.Hidden; Wind.rectMin.Visibility = Visibility.Visible; } else { Wind.main.BorderThickness = new Thickness(1); Wind.main.Margin = new Thickness(0); Wind.rectMax.Visibility = Visibility.Visible; Wind.rectMin.Visibility = Visibility.Hidden; } } } } ================================================ FILE: src/StartMenuManager.GUI/Utils/WindowRef.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - © Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- namespace StartMenuManager.GUI { public static class WindowRef { public static MainWindow Wind { get; set; } } } ================================================ FILE: src/StartMenuManager.GUI/WelcomeCard.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - © Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- using System.Windows; using static StartMenuManager.GUI.WindowRef; namespace StartMenuManager.GUI { public static class WelcomeCard { public static void InitEvents() { Wind.welcomeCard_CloseButton.Click += (sender, args) => CloseCardPressed(sender, args); } private static void CloseCardPressed(object sender, RoutedEventArgs args) { CloseCard(); Wind.Settings.DisplayWelcomeBox = false; Serialization.JsonSerializer.SaveSettings(Wind.Settings); } public static void CloseCard() { Wind.welcomeCard.Visibility = Visibility.Collapsed; } } } ================================================ FILE: src/StartMenuManager.GUI/app.manifest ================================================  ================================================ FILE: src/StartMenuManager.GUI.Installer/Product.wxs ================================================ (NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL") ================================================ FILE: src/StartMenuManager.GUI.Installer/StartMenuManager.GUI.Installer.wixproj ================================================ Debug x86 3.10 b7cbb2b3-65e2-44fb-aad6-9bd76884d09d 2.0 StartMenuManager.GUI.Installer Package bin\$(Configuration)\ obj\$(Configuration)\ Debug bin\$(Configuration)\ obj\$(Configuration)\ StartMenuManager.Builder {72692f58-2690-4677-a87b-a686bcaa6ff2} True True Binaries;Content;Satellites INSTALLFOLDER StartMenuManager.Core {f027fcb2-cc37-4d24-a2ab-072e19b87a18} True True Binaries;Content;Satellites INSTALLFOLDER StartMenuManager.GUI {ab31d486-50b4-4ff1-9e2c-3d8a29fb8ef4} True True Binaries;Content;Satellites INSTALLFOLDER StartMenuManager.PreUninstall {e9c16107-0f20-4b36-a65f-54d4290736ab} True True Binaries;Content;Satellites INSTALLFOLDER StartMenuManager.Runner {567580be-01ce-420c-86f5-1e91ef50beee} True True Binaries;Content;Satellites INSTALLFOLDER $(WixExtDir)\WixUtilExtension.dll WixUtilExtension $(WixExtDir)\WixNetFxExtension.dll WixNetFxExtension ================================================ FILE: src/StartMenuManager.GUI.Installer/netchecker.wxs ================================================ WIXNETFX4RELEASEINSTALLED >= "#$(var.NetFx472MinRelease)" ================================================ FILE: src/StartMenuManager.PreUninstall/App.config ================================================  ================================================ FILE: src/StartMenuManager.PreUninstall/Program.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - © Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- // This program does some cleaning up before uninstalling. // It removes all shortcuts from the start menu folder. using System; using System.IO; using Newtonsoft.Json; using StartMenuManager.Core.DataStructures; namespace StartMenuManager.PreUninstall { public class Program { private static SettingsConfig settings; public static int Main(string[] args) { string settingsPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"..\settings.json"); if (System.IO.File.Exists(settingsPath)) { StreamReader reader = new StreamReader(settingsPath); string contents = reader.ReadToEnd(); reader.Close(); settings = JsonConvert.DeserializeObject(contents); } else { settings = SettingsConfig.GetDefaultSettings(); } string shortcutsFilepath = settings.GetShortcutsFilePath(); // Delete the folder (within start menu folder) containing all the shortcuts if (Directory.Exists(shortcutsFilepath)) { Directory.Delete(shortcutsFilepath, true); } return 0; } } } ================================================ FILE: src/StartMenuManager.PreUninstall/Properties/AssemblyInfo.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - © Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- using System.Reflection; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("StartMenuManager.PreUninstall")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("StartMenuManager.PreUninstall")] [assembly: AssemblyCopyright("Copyright © 2020")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("e9c16107-0f20-4b36-a65f-54d4290736ab")] // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] ================================================ FILE: src/StartMenuManager.PreUninstall/StartMenuManager.PreUninstall.csproj ================================================  Debug AnyCPU {E9C16107-0F20-4B36-A65F-54D4290736AB} Exe StartMenuManager.PreUninstall StartMenuManager.PreUninstall v4.7.2 512 true true AnyCPU true full false bin\Debug\ DEBUG;TRACE prompt 4 AnyCPU pdbonly true bin\Release\ TRACE prompt 4 12.0.3 {f027fcb2-cc37-4d24-a2ab-072e19b87a18} StartMenuManager.Core ================================================ FILE: src/StartMenuManager.Runner/App.config ================================================ ================================================ FILE: src/StartMenuManager.Runner/Program.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - © Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- using System.IO; using StartMenuManager.Core.DataStructures; using StartMenuManager.Core.DataStructures.Actions; using StartMenuManager.Core.Serialization; namespace StartMenuManager.Runner { public class Program { public static void Main(string[] args) { if (args == null) { return; } if (args.Length == 0) { return; } if (!System.IO.File.Exists(args[0])) { return; } string shortcutJsonPath = args[0]; StreamReader reader = new StreamReader(shortcutJsonPath); string shortcutJson = reader.ReadToEnd(); reader.Close(); Shortcut shortcut = Serializer.DeserializeShortcut(shortcutJson); if (shortcut.IsValid() != null) { return; } ExecuteShortcut(shortcut); } public static void ExecuteShortcut(Shortcut shortcut) { foreach (Action action in shortcut.Actions) { switch (action.Type) { case "command": CommandAction ca = action as CommandAction; System.Diagnostics.Process process = new System.Diagnostics.Process(); System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo(); if (!ca.KeepOpen) { startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden; startInfo.Arguments = $"/C {ca.Command}"; } else { startInfo.Arguments = $"/k {ca.Command}"; } startInfo.FileName = "cmd.exe"; process.StartInfo = startInfo; process.Start(); break; case "file": FileAction fa = action as FileAction; System.Diagnostics.Process.Start(fa.Path); break; case "folder": FolderAction foa = action as FolderAction; System.Diagnostics.Process.Start(foa.Path); break; case "software": SoftwareAction sa = action as SoftwareAction; System.Diagnostics.Process.Start(sa.Path); break; case "website": WebsiteAction wa = action as WebsiteAction; System.Diagnostics.Process.Start(wa.Url); break; } } } } } ================================================ FILE: src/StartMenuManager.Runner/Properties/AssemblyInfo.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - © Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- using System.Reflection; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("StartMenuManager.Runner")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("StartMenuManager.Runner")] [assembly: AssemblyCopyright("Copyright © 2020")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("567580be-01ce-420c-86f5-1e91ef50beee")] // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] ================================================ FILE: src/StartMenuManager.Runner/StartMenuManager.Runner.csproj ================================================  Debug AnyCPU {567580BE-01CE-420C-86F5-1E91EF50BEEE} WinExe StartMenuManager.Runner StartMenuManager.Runner v4.7.2 512 true true AnyCPU true full false bin\Debug\ DEBUG;TRACE prompt 4 AnyCPU pdbonly true bin\Release\ TRACE prompt 4 icon-256.ico {f027fcb2-cc37-4d24-a2ab-072e19b87a18} StartMenuManager.Core ================================================ FILE: src/TextEditLib/AssemblyInfo.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- #pragma warning disable using System.Windows; [assembly: ThemeInfo( // where theme specific resource dictionaries are located // (used if a resource is not found in the page, // or application resource dictionaries) ResourceDictionaryLocation.None, // where the generic resource dictionary is located // (used if a resource is not found in the page, // app, or any theme specific resource dictionaries) ResourceDictionaryLocation.SourceAssembly )] ================================================ FILE: src/TextEditLib/Extensions/HighlightCurrentLineBackgroundRenderer.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - © Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- #pragma warning disable namespace TextEditLib.Extensions { using ICSharpCode.AvalonEdit; using ICSharpCode.AvalonEdit.Rendering; using System.Windows.Media; using System.Windows; /// /// AvalonEdit: highlight current line even when not focused /// /// Source: http://stackoverflow.com/questions/5072761/avalonedit-highlight-current-line-even-when-not-focused /// internal class HighlightCurrentLineBackgroundRenderer : IBackgroundRenderer { #region fields private readonly TextEdit _Editor; #endregion fields #region ctors /// /// Class Constructor from editor and SolidColorBrush definition /// /// public HighlightCurrentLineBackgroundRenderer(TextEdit editor) : this() { _Editor = editor; } /// /// Hidden class standard constructor /// protected HighlightCurrentLineBackgroundRenderer() { // Nothing to initialize here... } #endregion ctors #region properties /// /// Get the of the control. /// public KnownLayer Layer { get { return KnownLayer.Background; } } #endregion properties #region methods /// /// Draw the background line highlighting of the current line. /// /// /// public void Draw(TextView textView, DrawingContext drawingContext) { if (this._Editor == null) return; if (this._Editor.Document == null) return; if (_Editor.EditorCurrentLineBorderThickness == 0 && _Editor.EditorCurrentLineBackground == null) return; Pen borderPen = null; if (_Editor.EditorCurrentLineBorder != null) { borderPen = new Pen(_Editor.EditorCurrentLineBorder, _Editor.EditorCurrentLineBorderThickness); if (borderPen.CanFreeze) borderPen.Freeze(); } textView.EnsureVisualLines(); var currentLine = _Editor.Document.GetLineByOffset(_Editor.CaretOffset); foreach (var rect in BackgroundGeometryBuilder.GetRectsForSegment(textView, currentLine)) { drawingContext.DrawRectangle(_Editor.EditorCurrentLineBackground, borderPen, new Rect(rect.Location, new Size(textView.ActualWidth, rect.Height))); } } #endregion methods } } ================================================ FILE: src/TextEditLib/TextEdit.xaml ================================================  ================================================ FILE: src/TextEditLib/TextEdit.xaml.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - © Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- #pragma warning disable namespace TextEditLib { using ICSharpCode.AvalonEdit; using System.Windows; using System.Windows.Media; using TextEditLib.Extensions; /// /// Implements an AvalonEdit control textedit control with extensions. /// public class TextEdit : TextEditor { #region fields #region EditorCurrentLine Highlighting Colors public static readonly DependencyProperty EditorCurrentLineBackgroundProperty = DependencyProperty.Register("EditorCurrentLineBackground", typeof(Brush), typeof(TextEdit), new UIPropertyMetadata(new SolidColorBrush(Colors.Transparent))); public static readonly DependencyProperty EditorCurrentLineBorderProperty = DependencyProperty.Register("EditorCurrentLineBorder", typeof(Brush), typeof(TextEdit), new PropertyMetadata(new SolidColorBrush( Color.FromArgb(0x60, SystemColors.HighlightBrush.Color.R, SystemColors.HighlightBrush.Color.G, SystemColors.HighlightBrush.Color.B)))); public static readonly DependencyProperty EditorCurrentLineBorderThicknessProperty = DependencyProperty.Register("EditorCurrentLineBorderThickness", typeof(double), typeof(TextEdit), new PropertyMetadata(2.0d)); #endregion EditorCurrentLine Highlighting Colors #endregion fields #region ctors /// /// Static class constructor /// static TextEdit() { DefaultStyleKeyProperty.OverrideMetadata(typeof(TextEdit), new FrameworkPropertyMetadata(typeof(TextEdit))); } /// /// Class constructor /// public TextEdit() { this.Loaded += TextEdit_Loaded; } #endregion ctors #region properties #region EditorCurrentLine Highlighting Colors /// /// Style the background color of the current editor line /// public Brush EditorCurrentLineBackground { get { return (Brush)GetValue(EditorCurrentLineBackgroundProperty); } set { SetValue(EditorCurrentLineBackgroundProperty, value); } } public Brush EditorCurrentLineBorder { get { return (Brush)GetValue(EditorCurrentLineBorderProperty); } set { SetValue(EditorCurrentLineBorderProperty, value); } } public double EditorCurrentLineBorderThickness { get { return (double)GetValue(EditorCurrentLineBorderThicknessProperty); } set { SetValue(EditorCurrentLineBorderThicknessProperty, value); } } #endregion EditorCurrentLine Highlighting Colors #endregion properties #region methods /// /// Method is invoked when the control is loaded for the first time. /// /// /// private void TextEdit_Loaded(object sender, RoutedEventArgs e) { AdjustCurrentLineBackground(); } /// /// Reset the to be used for highlighting the current editor line. /// private void AdjustCurrentLineBackground() { HighlightCurrentLineBackgroundRenderer oldRenderer = null; // Make sure there is only one of this type of background renderer // Otherwise, we might keep adding and WPF keeps drawing them on top of each other foreach (var item in this.TextArea.TextView.BackgroundRenderers) { if (item != null) { if (item is HighlightCurrentLineBackgroundRenderer) { oldRenderer = item as HighlightCurrentLineBackgroundRenderer; } } } if (oldRenderer != null) this.TextArea.TextView.BackgroundRenderers.Remove(oldRenderer); this.TextArea.TextView.BackgroundRenderers.Add(new HighlightCurrentLineBackgroundRenderer(this)); } #endregion methods } } ================================================ FILE: src/TextEditLib/TextEditLib.csproj ================================================  netcoreapp3.0;net4.5.2 true Code TextEdit.xaml all runtime; build; native; contentfiles; analyzers; buildtransitive Designer Designer Designer Designer ================================================ FILE: src/TextEditLib/Themes/DarkBrushs.xaml ================================================  #1ba1e2 ================================================ FILE: src/TextEditLib/Themes/Generic.xaml ================================================  ================================================ FILE: src/TextEditLib/Themes/Icons.xaml ================================================  ================================================ FILE: src/TextEditLib/Themes/LightBrushs.xaml ================================================  #1ba1e2 ================================================ FILE: src/TextEditLib/Themes/ResourceKeys.cs ================================================ // ------------------------------------------------------------------------------------------------- // Start Menu Manager - Copyright 2020 - Jam-Es.com // Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. // ------------------------------------------------------------------------------------------------- #pragma warning disable namespace TextEditLib.Themes { using System.Windows; public static class ResourceKeys { #region Accent Keys /// /// Accent Color Key - This Color key is used to accent elements in the UI /// (e.g.: Color of Activated Normal Window Frame, ResizeGrip, Focus or MouseOver input elements) /// public static readonly ComponentResourceKey ControlAccentColorKey = new ComponentResourceKey(typeof(ResourceKeys), "ControlAccentColorKey"); /// /// Accent Brush Key - This Brush key is used to accent elements in the UI /// (e.g.: Color of Activated Normal Window Frame, ResizeGrip, Focus or MouseOver input elements) /// public static readonly ComponentResourceKey ControlAccentBrushKey = new ComponentResourceKey(typeof(ResourceKeys), "ControlAccentBrushKey"); #endregion Accent Keys #region TextEditor BrushKeys public static readonly ComponentResourceKey EditorBackground = new ComponentResourceKey(typeof(ResourceKeys), "EditorBackground"); public static readonly ComponentResourceKey EditorForeground = new ComponentResourceKey(typeof(ResourceKeys), "EditorForeground"); public static readonly ComponentResourceKey EditorLineNumbersForeground = new ComponentResourceKey(typeof(ResourceKeys), "EditorLineNumbersForeground"); public static readonly ComponentResourceKey EditorSelectionBrush = new ComponentResourceKey(typeof(ResourceKeys), "EditorSelectionBrush"); public static readonly ComponentResourceKey EditorSelectionBorder = new ComponentResourceKey(typeof(ResourceKeys), "EditorSelectionBorder"); public static readonly ComponentResourceKey EditorNonPrintableCharacterBrush = new ComponentResourceKey(typeof(ResourceKeys), "EditorNonPrintableCharacterBrush"); public static readonly ComponentResourceKey EditorLinkTextForegroundBrush = new ComponentResourceKey(typeof(ResourceKeys), "EditorLinkTextForegroundBrush"); public static readonly ComponentResourceKey EditorLinkTextBackgroundBrush = new ComponentResourceKey(typeof(ResourceKeys), "EditorLinkTextBackgroundBrush"); #region DiffView Currentline Keys /// /// Gets the background color for highlighting for the currently highlighed line. /// public static readonly ComponentResourceKey EditorCurrentLineBackgroundBrushKey = new ComponentResourceKey(typeof(ResourceKeys), "EditorCurrentLineBackgroundBrushKey"); /// /// Gets the border color for highlighting for the currently highlighed line. /// public static readonly ComponentResourceKey EditorCurrentLineBorderBrushKey = new ComponentResourceKey(typeof(ResourceKeys), "EditorCurrentLineBorderBrushKey"); /// /// Gets the border thickness for highlighting for the currently highlighed line. /// public static readonly ComponentResourceKey EditorCurrentLineBorderThicknessKey = new ComponentResourceKey(typeof(ResourceKeys), "EditorCurrentLineBorderThicknessKey"); #endregion DiffView Currentline Keys #endregion TextEditor BrushKeys } } ================================================ FILE: stylecop.json ================================================ { "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", "settings": { "documentationRules": { "companyName": "Jam-Es.com", "copyrightText": "-------------------------------------------------------------------------------------------------\nStart Menu Manager - © Copyright 2020 - {companyName}\nLicensed under the {licenseName} License ({licenseName}). See {licenseFile} in the repo root for license information.\n-------------------------------------------------------------------------------------------------", "variables": { "licenseName": "MIT", "licenseFile": "LICENSE" }, "xmlHeader": false, "headerDecoration": "-------------------------------------------------------------------------------------------------" }, "orderingRules": { "systemUsingDirectivesFirst": true, "usingDirectivesPlacement": "outsideNamespace", "elementOrder": [ "kind" ] }, "indentation": { "useTabs": false, "indentationSize": 4, "tabSize": 4 } } }