├── .gitattributes
├── .github
└── ISSUE_TEMPLATE
│ ├── bug_report.yml
│ ├── config.yaml
│ └── feature_request.yaml
├── .gitignore
├── BoTech.DesignerForAvalonia.Android
├── BoTech.DesignerForAvalonia.Android.csproj
├── Icon.png
├── MainActivity.cs
├── Properties
│ └── AndroidManifest.xml
└── Resources
│ ├── drawable
│ └── splash_screen.xml
│ ├── values-night
│ └── colors.xml
│ └── values
│ ├── colors.xml
│ └── styles.xml
├── BoTech.DesignerForAvalonia.Browser
├── BoTech.DesignerForAvalonia.Browser.csproj
├── Program.cs
├── Properties
│ ├── AssemblyInfo.cs
│ └── launchSettings.json
├── runtimeconfig.template.json
└── wwwroot
│ ├── app.css
│ ├── favicon.ico
│ ├── index.html
│ └── main.js
├── BoTech.DesignerForAvalonia.Desktop
├── BoTech.DesignerForAvalonia.Desktop.csproj
├── Program.cs
└── app.manifest
├── BoTech.DesignerForAvalonia.Tests
├── BoTech.DesignerForAvalonia.Tests.csproj
└── Services
│ └── Binding
│ └── BindingManagerTest.cs
├── BoTech.DesignerForAvalonia.iOS
├── AppDelegate.cs
├── BoTech.DesignerForAvalonia.iOS.csproj
├── Entitlements.plist
├── Info.plist
├── Main.cs
└── Resources
│ └── LaunchScreen.xib
├── BoTech.DesignerForAvalonia.sln
├── BoTech.DesignerForAvalonia
├── App.axaml
├── App.axaml.cs
├── Assets
│ ├── BoTechLogoNew.png
│ ├── BoTech_DesignerForAvalonia_Mini.ico
│ ├── BoTech_DesignerForAvalonia_Mini.png
│ ├── BoTech_DesignerForAvalonia_Small.png
│ ├── BoTech_DesignerForAvalonia_WithText.png
│ └── BoTech_DesignerForAvalonia_WithText_NoBG.png
├── BoTech.DesignerForAvalonia.csproj
├── Controller
│ └── Editor
│ │ ├── EditorController.cs
│ │ └── ProjectController.cs
├── Models
│ ├── Binding
│ │ ├── ExtractedRelativeSource.cs
│ │ └── ValueType.cs
│ ├── Editor
│ │ ├── EDragAndDropOperation.cs
│ │ └── TreeViewNodeBase.cs
│ ├── Project
│ │ ├── Binding.cs
│ │ ├── CSharp
│ │ │ ├── ExtractedBindingInfo.cs
│ │ │ ├── ExtractedClassInfo.cs
│ │ │ ├── ExtractedMethodInfo.cs
│ │ │ ├── ExtractedPropertyInfo.cs
│ │ │ └── Modifier.cs
│ │ ├── DisplayableProjectInfo.cs
│ │ ├── OpenableProject.cs
│ │ ├── Project.cs
│ │ ├── ProjectView.cs
│ │ └── ProjectViewModel.cs
│ └── XML
│ │ └── XmlControl.cs
├── Services
│ ├── Avalonia
│ │ ├── CloneService.cs
│ │ └── TypeCastingService.cs
│ ├── Binding
│ │ └── BindingManager.cs
│ ├── CSharp
│ │ └── CSharpParser.cs
│ ├── PropertiesView
│ │ ├── ControlsCreator.cs
│ │ ├── ControlsCreatorAvalonia.cs
│ │ ├── ControlsCreatorObject.cs
│ │ └── EditBoxOptions.cs
│ └── XML
│ │ ├── Deserializer.cs
│ │ └── Serializer.cs
├── Templates
│ └── Editor
│ │ └── PropertiesView
│ │ ├── AppearanceViewTemplate.cs
│ │ ├── ContentViewTemplate.cs
│ │ ├── IViewTemplate.cs
│ │ ├── InputViewTemplate.cs
│ │ ├── LayoutViewTemplate.cs
│ │ └── StandardViewTemplate.cs
├── ViewLocator.cs
├── ViewModels
│ ├── AboutViewModel.cs
│ ├── Abstraction
│ │ └── CloseablePageViewModel.cs
│ ├── Editor
│ │ ├── Dialogs
│ │ │ ├── GenericDialogViewModel.cs
│ │ │ └── ProjectColorDialogViewModel.cs
│ │ ├── ItemsExplorerViewModel.cs
│ │ ├── PreviewViewModel.cs
│ │ ├── PropertiesViewModel.cs
│ │ ├── SolutionExplorerViewModel.cs
│ │ ├── TopNavigationViewModel.cs
│ │ └── ViewHierarchyViewModel.cs
│ ├── LoadingViewModel.cs
│ ├── MainViewModel.cs
│ ├── ProjectStartViewModel.cs
│ └── ViewModelBase.cs
└── Views
│ ├── AboutView.axaml
│ ├── AboutView.axaml.cs
│ ├── Abstraction
│ └── CloseablePageCodeBehind.cs
│ ├── Editor
│ ├── Dialogs
│ │ ├── GenericDialogView.axaml
│ │ ├── GenericDialogView.axaml.cs
│ │ ├── ProjectColorDialogView.axaml
│ │ ├── ProjectColorDialogView.axaml.cs
│ │ ├── PropertiesDialogView.axaml
│ │ └── PropertiesDialogView.axaml.cs
│ ├── ItemsExplorerView.axaml
│ ├── ItemsExplorerView.axaml.cs
│ ├── PreviewView.axaml
│ ├── PreviewView.axaml.cs
│ ├── PropertiesView.axaml
│ ├── PropertiesView.axaml.cs
│ ├── SolutionExplorerView.axaml
│ ├── SolutionExplorerView.axaml.cs
│ ├── StatusConsoleView.axaml
│ ├── StatusConsoleView.axaml.cs
│ ├── TopNavigationView.axaml
│ ├── TopNavigationView.axaml.cs
│ ├── ViewHierarchyView.axaml
│ └── ViewHierarchyView.axaml.cs
│ ├── LoadingView.axaml
│ ├── LoadingView.axaml.cs
│ ├── MainView.axaml
│ ├── MainView.axaml.cs
│ ├── MainWindow.axaml
│ ├── MainWindow.axaml.cs
│ ├── ProjectStartView.axaml
│ └── ProjectStartView.axaml.cs
├── CODE_OF_CONDUCT.md
├── Contributing.md
├── Directory.Build.props
├── Docs
└── Code
│ ├── .$BoTech.AvaloniaDesigner.drawio.bkp
│ ├── BoTech.AvaloniaDesigner.drawio
│ ├── MainCodeStructure.md
│ └── README.md
├── LICENSE
├── README.md
└── global.json
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.yml:
--------------------------------------------------------------------------------
1 | name: Bug Report
2 | description: Report an bug in the BoTech.DesignerForAvalonia
3 | labels: ["bug"]
4 | body:
5 | - type: textarea
6 | id: what-happened
7 | attributes:
8 | label: Describe the bug
9 | description: A clear and concise description of what the bug is.
10 | validations:
11 | required: true
12 | - type: textarea
13 | id: steps
14 | attributes:
15 | label: To Reproduce
16 | description: Steps to reproduce the behavior.
17 | validations:
18 | required: true
19 | - type: textarea
20 | id: what-expected
21 | attributes:
22 | label: Expected behavior
23 | description: A clear and concise description of what you expected to happen.
24 | - type: input
25 | id: version
26 | attributes:
27 | label: BoTech.DesignerForAvalonia Version
28 | placeholder: e.g. V1.0.19, V1.1.0 or V1.1.1
29 | validations:
30 | required: true
31 | - type: dropdown
32 | id: OS
33 | attributes:
34 | label: Operating System
35 | multiple: true
36 | options:
37 | - Windows
38 | - macOS
39 | - Linux
40 | - Web
41 | - Android
42 | - iOS
43 | - type: textarea
44 | id: additional-info
45 | attributes:
46 | label: Additional context
47 | description: |
48 | Add any other context about the problem here.
49 | If applicable, add screenshots to help explain your problem.
50 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yaml:
--------------------------------------------------------------------------------
1 | blank_issues_enabled: false
2 | contact_links:
3 | - name: Questions, Discussions, Ideas
4 | url: https://github.com/BoTech-Development/BoTech.DesignerForAvalonia/discussions/new
5 | about: Please ask and answer questions here
6 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.yaml:
--------------------------------------------------------------------------------
1 | name: Feature request
2 | description: Suggest an idea for this project
3 | labels: ["feature"]
4 | body:
5 | - type: textarea
6 | id: problem
7 | attributes:
8 | label: Is your feature request related to ani issue? Please describe and paste a link of the issue.
9 | description: A clear and concise description of what the problem is.
10 | validations:
11 | required: true
12 | - type: textarea
13 | id: solution
14 | attributes:
15 | label: Describe the solution you'd like
16 | description: A clear and concise description of what you want to happen. Which feature should be implemented.
17 | validations:
18 | required: true
19 | - type: textarea
20 | id: implementation
21 | attributes:
22 | label: Do you have an idea how to implement your feature?
23 | description: A clear and precise description of how we can implement the feature. Please use the repository as reference
24 | validations:
25 | required: false
26 | - type: textarea
27 | id: alternatives
28 | attributes:
29 | label: Describe alternatives you've considered
30 | description: A clear and concise description of any alternative solutions or features you've considered.
31 | - type: textarea
32 | id: additional-context
33 | attributes:
34 | label: Additional context
35 | description: Add any other context or screenshots about the feature request here.
36 |
--------------------------------------------------------------------------------
/BoTech.DesignerForAvalonia.Android/BoTech.DesignerForAvalonia.Android.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | Exe
4 | net9.0-android
5 | 21
6 | enable
7 | com.CompanyName.AvaloniaTest
8 | 1
9 | 1.0
10 | apk
11 | False
12 |
13 |
14 |
15 |
16 | Resources\drawable\Icon.png
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/BoTech.DesignerForAvalonia.Android/Icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BoTech-Development/BoTech.DesignerForAvalonia/f5617e067f6949a588bf501d666abc3adc08daa7/BoTech.DesignerForAvalonia.Android/Icon.png
--------------------------------------------------------------------------------
/BoTech.DesignerForAvalonia.Android/MainActivity.cs:
--------------------------------------------------------------------------------
1 | using Android.App;
2 | using Android.Content.PM;
3 |
4 | using Avalonia;
5 | using Avalonia.Android;
6 | using Avalonia.ReactiveUI;
7 |
8 | namespace BoTech.DesignerForAvalonia.Android;
9 |
10 | [Activity(
11 | Label = "BoTech.DesignerForAvalonia.Android",
12 | Theme = "@style/MyTheme.NoActionBar",
13 | Icon = "@drawable/icon",
14 | MainLauncher = true,
15 | ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize | ConfigChanges.UiMode)]
16 | public class MainActivity : AvaloniaMainActivity
17 | {
18 | protected override AppBuilder CustomizeAppBuilder(AppBuilder builder)
19 | {
20 | return base.CustomizeAppBuilder(builder)
21 | .WithInterFont()
22 | .UseReactiveUI();
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/BoTech.DesignerForAvalonia.Android/Properties/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/BoTech.DesignerForAvalonia.Android/Resources/drawable/splash_screen.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
6 |
7 |
8 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/BoTech.DesignerForAvalonia.Android/Resources/values-night/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #212121
4 |
5 |
--------------------------------------------------------------------------------
/BoTech.DesignerForAvalonia.Android/Resources/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FFFFFF
4 |
5 |
--------------------------------------------------------------------------------
/BoTech.DesignerForAvalonia.Android/Resources/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/BoTech.DesignerForAvalonia.Browser/BoTech.DesignerForAvalonia.Browser.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net9.0-browser
4 | Exe
5 | true
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/BoTech.DesignerForAvalonia.Browser/Program.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.Versioning;
2 | using System.Threading.Tasks;
3 |
4 | using Avalonia;
5 | using Avalonia.Browser;
6 | using Avalonia.ReactiveUI;
7 |
8 | using BoTech.DesignerForAvalonia;
9 |
10 | internal sealed partial class Program
11 | {
12 | private static Task Main(string[] args) => BuildAvaloniaApp()
13 | .WithInterFont()
14 | .UseReactiveUI()
15 | .StartBrowserAppAsync("out");
16 |
17 | public static AppBuilder BuildAvaloniaApp()
18 | => AppBuilder.Configure();
19 | }
20 |
--------------------------------------------------------------------------------
/BoTech.DesignerForAvalonia.Browser/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | [assembly:System.Runtime.Versioning.SupportedOSPlatform("browser")]
2 |
--------------------------------------------------------------------------------
/BoTech.DesignerForAvalonia.Browser/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "profiles": {
3 | "BoTech.AvaloniaDesigner.Browser": {
4 | "commandName": "Project",
5 | "launchBrowser": true,
6 | "environmentVariables": {
7 | "ASPNETCORE_ENVIRONMENT": "Development"
8 | },
9 | "applicationUrl": "https://localhost:7169;http://localhost:5235",
10 | "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/BoTech.DesignerForAvalonia.Browser/runtimeconfig.template.json:
--------------------------------------------------------------------------------
1 | {
2 | "wasmHostProperties": {
3 | "perHostConfig": [
4 | {
5 | "name": "browser",
6 | "host": "browser"
7 | }
8 | ]
9 | }
10 | }
--------------------------------------------------------------------------------
/BoTech.DesignerForAvalonia.Browser/wwwroot/app.css:
--------------------------------------------------------------------------------
1 | /* HTML styles for the splash screen */
2 | .avalonia-splash {
3 | position: absolute;
4 | height: 100%;
5 | width: 100%;
6 | background: white;
7 | font-family: 'Outfit', sans-serif;
8 | justify-content: center;
9 | align-items: center;
10 | display: flex;
11 | pointer-events: none;
12 | }
13 |
14 | /* Light theme styles */
15 | @media (prefers-color-scheme: light) {
16 | .avalonia-splash {
17 | background: white;
18 | }
19 |
20 | .avalonia-splash h2 {
21 | color: #1b2a4e;
22 | }
23 |
24 | .avalonia-splash a {
25 | color: #0D6EFD;
26 | }
27 | }
28 |
29 | @media (prefers-color-scheme: dark) {
30 | .avalonia-splash {
31 | background: #1b2a4e;
32 | }
33 |
34 | .avalonia-splash h2 {
35 | color: white;
36 | }
37 |
38 | .avalonia-splash a {
39 | color: white;
40 | }
41 | }
42 |
43 | .avalonia-splash h2 {
44 | font-weight: 400;
45 | font-size: 1.5rem;
46 | }
47 |
48 | .avalonia-splash a {
49 | text-decoration: none;
50 | font-size: 2.5rem;
51 | display: block;
52 | }
53 |
54 | .avalonia-splash.splash-close {
55 | transition: opacity 200ms, display 200ms;
56 | display: none;
57 | opacity: 0;
58 | }
59 |
--------------------------------------------------------------------------------
/BoTech.DesignerForAvalonia.Browser/wwwroot/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BoTech-Development/BoTech.DesignerForAvalonia/f5617e067f6949a588bf501d666abc3adc08daa7/BoTech.DesignerForAvalonia.Browser/wwwroot/favicon.ico
--------------------------------------------------------------------------------
/BoTech.DesignerForAvalonia.Browser/wwwroot/main.js:
--------------------------------------------------------------------------------
1 | import { dotnet } from './_framework/dotnet.js'
2 |
3 | const is_browser = typeof window != "undefined";
4 | if (!is_browser) throw new Error(`Expected to be running in a browser`);
5 |
6 | const dotnetRuntime = await dotnet
7 | .withDiagnosticTracing(false)
8 | .withApplicationArgumentsFromQuery()
9 | .create();
10 |
11 | const config = dotnetRuntime.getConfig();
12 |
13 | await dotnetRuntime.runMain(config.mainAssemblyName, [globalThis.location.href]);
14 |
--------------------------------------------------------------------------------
/BoTech.DesignerForAvalonia.Desktop/BoTech.DesignerForAvalonia.Desktop.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | WinExe
4 |
6 | net9.0
7 | enable
8 | true
9 | app.manifest
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/BoTech.DesignerForAvalonia.Desktop/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | using Avalonia;
4 | using Avalonia.ReactiveUI;
5 |
6 | namespace BoTech.DesignerForAvalonia.Desktop;
7 |
8 | class Program
9 | {
10 | // Initialization code. Don't use any Avalonia, third-party APIs or any
11 | // SynchronizationContext-reliant code before AppMain is called: things aren't initialized
12 | // yet and stuff might break.
13 | [STAThread]
14 | public static void Main(string[] args) => BuildAvaloniaApp()
15 | .StartWithClassicDesktopLifetime(args);
16 |
17 | // Avalonia configuration, don't remove; also used by visual designer.
18 | public static AppBuilder BuildAvaloniaApp()
19 | => AppBuilder.Configure()
20 | .UsePlatformDetect()
21 | .WithInterFont()
22 | .LogToTrace()
23 | .UseReactiveUI();
24 | }
25 |
--------------------------------------------------------------------------------
/BoTech.DesignerForAvalonia.Desktop/app.manifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
9 |
10 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/BoTech.DesignerForAvalonia.Tests/BoTech.DesignerForAvalonia.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net9.0
5 |
6 | false
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/BoTech.DesignerForAvalonia.Tests/Services/Binding/BindingManagerTest.cs:
--------------------------------------------------------------------------------
1 | using BoTech.DesignerForAvalonia.Services.Binding;
2 | using JetBrains.Annotations;
3 | using Microsoft.VisualStudio.TestTools.UnitTesting;
4 |
5 | namespace BoTech.DesignerForAvalonia.Tests.Services.Binding;
6 |
7 | [TestClass]
8 | [TestSubject(typeof(BindingManager))]
9 | public class BindingManagerTest
10 | {
11 |
12 | [TestMethod]
13 | public void TestNodeTree()
14 | {
15 | BindingManager.ParseBindingsFromSource(
16 | "Binding Title, RelativeSource={RelativeSource Tree=Logical, Mode=FindAncestor, AncestorType=Window}, TargetNullValue={Binding MyInt}");
17 | }
18 | }
--------------------------------------------------------------------------------
/BoTech.DesignerForAvalonia.iOS/AppDelegate.cs:
--------------------------------------------------------------------------------
1 | using Avalonia;
2 | using Avalonia.iOS;
3 | using Avalonia.ReactiveUI;
4 |
5 | using Foundation;
6 |
7 | namespace BoTech.DesignerForAvalonia.iOS;
8 |
9 | // The UIApplicationDelegate for the application. This class is responsible for launching the
10 | // User Interface of the application, as well as listening (and optionally responding) to
11 | // application events from iOS.
12 | [Register("AppDelegate")]
13 | public partial class AppDelegate : AvaloniaAppDelegate
14 | {
15 | protected override AppBuilder CustomizeAppBuilder(AppBuilder builder)
16 | {
17 | return base.CustomizeAppBuilder(builder)
18 | .WithInterFont()
19 | .UseReactiveUI();
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/BoTech.DesignerForAvalonia.iOS/BoTech.DesignerForAvalonia.iOS.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | Exe
4 | net9.0-ios
5 | 13.0
6 | enable
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/BoTech.DesignerForAvalonia.iOS/Entitlements.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/BoTech.DesignerForAvalonia.iOS/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDisplayName
6 | AvaloniaTest
7 | CFBundleIdentifier
8 | companyName.AvaloniaTest
9 | CFBundleShortVersionString
10 | 1.0
11 | CFBundleVersion
12 | 1.0
13 | LSRequiresIPhoneOS
14 |
15 | MinimumOSVersion
16 | 10.0
17 | UIDeviceFamily
18 |
19 | 1
20 | 2
21 |
22 | UILaunchStoryboardName
23 | LaunchScreen
24 | UIRequiredDeviceCapabilities
25 |
26 | armv7
27 |
28 | UISupportedInterfaceOrientations
29 |
30 | UIInterfaceOrientationPortrait
31 | UIInterfaceOrientationPortraitUpsideDown
32 | UIInterfaceOrientationLandscapeLeft
33 | UIInterfaceOrientationLandscapeRight
34 |
35 | UISupportedInterfaceOrientations~ipad
36 |
37 | UIInterfaceOrientationPortrait
38 | UIInterfaceOrientationPortraitUpsideDown
39 | UIInterfaceOrientationLandscapeLeft
40 | UIInterfaceOrientationLandscapeRight
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/BoTech.DesignerForAvalonia.iOS/Main.cs:
--------------------------------------------------------------------------------
1 | using UIKit;
2 |
3 | namespace BoTech.DesignerForAvalonia.iOS;
4 |
5 | public class Application
6 | {
7 | // This is the main entry point of the application.
8 | static void Main(string[] args)
9 | {
10 | // if you want to use a different Application Delegate class from "AppDelegate"
11 | // you can specify it here.
12 | UIApplication.Main(args, null, typeof(AppDelegate));
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/BoTech.DesignerForAvalonia.iOS/Resources/LaunchScreen.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
21 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/BoTech.DesignerForAvalonia.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.12.35521.163 d17.12
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BoTech.DesignerForAvalonia", "BoTech.DesignerForAvalonia\BoTech.DesignerForAvalonia.csproj", "{5CCA3558-0F1B-4429-A435-32DF9D7EC5EA}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BoTech.DesignerForAvalonia.Android", "BoTech.DesignerForAvalonia.Android\BoTech.DesignerForAvalonia.Android.csproj", "{A86AFF4E-103A-4018-B137-8D27FED26BAD}"
9 | EndProject
10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BoTech.DesignerForAvalonia.Browser", "BoTech.DesignerForAvalonia.Browser\BoTech.DesignerForAvalonia.Browser.csproj", "{E5B4F8E5-C1CB-4B46-A9FB-62F85DB5D5A1}"
11 | EndProject
12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BoTech.DesignerForAvalonia.Desktop", "BoTech.DesignerForAvalonia.Desktop\BoTech.DesignerForAvalonia.Desktop.csproj", "{46094B01-28F9-4438-8E6B-0358102F66C9}"
13 | EndProject
14 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BoTech.DesignerForAvalonia.iOS", "BoTech.DesignerForAvalonia.iOS\BoTech.DesignerForAvalonia.iOS.csproj", "{797C477A-EBED-4DD4-BEA6-376DAEF9B00B}"
15 | EndProject
16 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BoTech.DesignerForAvalonia.Tests", "BoTech.DesignerForAvalonia.Tests\BoTech.DesignerForAvalonia.Tests.csproj", "{FBDFCCA0-6709-495D-B784-24BD0F7D3232}"
17 | EndProject
18 | Global
19 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
20 | Debug|Any CPU = Debug|Any CPU
21 | Release|Any CPU = Release|Any CPU
22 | EndGlobalSection
23 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
24 | {5CCA3558-0F1B-4429-A435-32DF9D7EC5EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
25 | {5CCA3558-0F1B-4429-A435-32DF9D7EC5EA}.Debug|Any CPU.Build.0 = Debug|Any CPU
26 | {5CCA3558-0F1B-4429-A435-32DF9D7EC5EA}.Release|Any CPU.ActiveCfg = Release|Any CPU
27 | {5CCA3558-0F1B-4429-A435-32DF9D7EC5EA}.Release|Any CPU.Build.0 = Release|Any CPU
28 | {A86AFF4E-103A-4018-B137-8D27FED26BAD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
29 | {A86AFF4E-103A-4018-B137-8D27FED26BAD}.Debug|Any CPU.Build.0 = Debug|Any CPU
30 | {A86AFF4E-103A-4018-B137-8D27FED26BAD}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
31 | {A86AFF4E-103A-4018-B137-8D27FED26BAD}.Release|Any CPU.ActiveCfg = Release|Any CPU
32 | {A86AFF4E-103A-4018-B137-8D27FED26BAD}.Release|Any CPU.Build.0 = Release|Any CPU
33 | {A86AFF4E-103A-4018-B137-8D27FED26BAD}.Release|Any CPU.Deploy.0 = Release|Any CPU
34 | {E5B4F8E5-C1CB-4B46-A9FB-62F85DB5D5A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
35 | {E5B4F8E5-C1CB-4B46-A9FB-62F85DB5D5A1}.Debug|Any CPU.Build.0 = Debug|Any CPU
36 | {E5B4F8E5-C1CB-4B46-A9FB-62F85DB5D5A1}.Release|Any CPU.ActiveCfg = Release|Any CPU
37 | {E5B4F8E5-C1CB-4B46-A9FB-62F85DB5D5A1}.Release|Any CPU.Build.0 = Release|Any CPU
38 | {46094B01-28F9-4438-8E6B-0358102F66C9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
39 | {46094B01-28F9-4438-8E6B-0358102F66C9}.Debug|Any CPU.Build.0 = Debug|Any CPU
40 | {46094B01-28F9-4438-8E6B-0358102F66C9}.Release|Any CPU.ActiveCfg = Release|Any CPU
41 | {46094B01-28F9-4438-8E6B-0358102F66C9}.Release|Any CPU.Build.0 = Release|Any CPU
42 | {797C477A-EBED-4DD4-BEA6-376DAEF9B00B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
43 | {797C477A-EBED-4DD4-BEA6-376DAEF9B00B}.Debug|Any CPU.Build.0 = Debug|Any CPU
44 | {797C477A-EBED-4DD4-BEA6-376DAEF9B00B}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
45 | {797C477A-EBED-4DD4-BEA6-376DAEF9B00B}.Release|Any CPU.ActiveCfg = Release|Any CPU
46 | {797C477A-EBED-4DD4-BEA6-376DAEF9B00B}.Release|Any CPU.Build.0 = Release|Any CPU
47 | {797C477A-EBED-4DD4-BEA6-376DAEF9B00B}.Release|Any CPU.Deploy.0 = Release|Any CPU
48 | {FBDFCCA0-6709-495D-B784-24BD0F7D3232}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
49 | {FBDFCCA0-6709-495D-B784-24BD0F7D3232}.Debug|Any CPU.Build.0 = Debug|Any CPU
50 | {FBDFCCA0-6709-495D-B784-24BD0F7D3232}.Release|Any CPU.ActiveCfg = Release|Any CPU
51 | {FBDFCCA0-6709-495D-B784-24BD0F7D3232}.Release|Any CPU.Build.0 = Release|Any CPU
52 | EndGlobalSection
53 | GlobalSection(SolutionProperties) = preSolution
54 | HideSolutionNode = FALSE
55 | EndGlobalSection
56 | EndGlobal
57 |
--------------------------------------------------------------------------------
/BoTech.DesignerForAvalonia/App.axaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/BoTech.DesignerForAvalonia/App.axaml.cs:
--------------------------------------------------------------------------------
1 | using Avalonia;
2 | using Avalonia.Controls.ApplicationLifetimes;
3 | using Avalonia.Markup.Xaml;
4 | using BoTech.DesignerForAvalonia.ViewModels;
5 | using BoTech.DesignerForAvalonia.Views;
6 |
7 | namespace BoTech.DesignerForAvalonia;
8 |
9 | public partial class App : Application
10 | {
11 | public override void Initialize()
12 | {
13 | AvaloniaXamlLoader.Load(this);
14 | }
15 |
16 | public override void OnFrameworkInitializationCompleted()
17 | {
18 | if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
19 | {
20 | desktop.MainWindow = new MainWindow
21 | {
22 | DataContext = new MainViewModel()
23 | };
24 | }
25 | else if (ApplicationLifetime is ISingleViewApplicationLifetime singleViewPlatform)
26 | {
27 | singleViewPlatform.MainView = new MainView
28 | {
29 | DataContext = new MainViewModel()
30 | };
31 | }
32 |
33 | base.OnFrameworkInitializationCompleted();
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/BoTech.DesignerForAvalonia/Assets/BoTechLogoNew.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BoTech-Development/BoTech.DesignerForAvalonia/f5617e067f6949a588bf501d666abc3adc08daa7/BoTech.DesignerForAvalonia/Assets/BoTechLogoNew.png
--------------------------------------------------------------------------------
/BoTech.DesignerForAvalonia/Assets/BoTech_DesignerForAvalonia_Mini.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BoTech-Development/BoTech.DesignerForAvalonia/f5617e067f6949a588bf501d666abc3adc08daa7/BoTech.DesignerForAvalonia/Assets/BoTech_DesignerForAvalonia_Mini.ico
--------------------------------------------------------------------------------
/BoTech.DesignerForAvalonia/Assets/BoTech_DesignerForAvalonia_Mini.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BoTech-Development/BoTech.DesignerForAvalonia/f5617e067f6949a588bf501d666abc3adc08daa7/BoTech.DesignerForAvalonia/Assets/BoTech_DesignerForAvalonia_Mini.png
--------------------------------------------------------------------------------
/BoTech.DesignerForAvalonia/Assets/BoTech_DesignerForAvalonia_Small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BoTech-Development/BoTech.DesignerForAvalonia/f5617e067f6949a588bf501d666abc3adc08daa7/BoTech.DesignerForAvalonia/Assets/BoTech_DesignerForAvalonia_Small.png
--------------------------------------------------------------------------------
/BoTech.DesignerForAvalonia/Assets/BoTech_DesignerForAvalonia_WithText.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BoTech-Development/BoTech.DesignerForAvalonia/f5617e067f6949a588bf501d666abc3adc08daa7/BoTech.DesignerForAvalonia/Assets/BoTech_DesignerForAvalonia_WithText.png
--------------------------------------------------------------------------------
/BoTech.DesignerForAvalonia/Assets/BoTech_DesignerForAvalonia_WithText_NoBG.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BoTech-Development/BoTech.DesignerForAvalonia/f5617e067f6949a588bf501d666abc3adc08daa7/BoTech.DesignerForAvalonia/Assets/BoTech_DesignerForAvalonia_WithText_NoBG.png
--------------------------------------------------------------------------------
/BoTech.DesignerForAvalonia/BoTech.DesignerForAvalonia.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net9.0
4 | enable
5 | latest
6 | true
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/BoTech.DesignerForAvalonia/Models/Binding/ExtractedRelativeSource.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Avalonia.Data;
3 |
4 | namespace BoTech.DesignerForAvalonia.Models.Binding;
5 |
6 | public class ExtractedRelativeSource
7 | {
8 |
9 | private int _ancestorLevel = 1;
10 | ///
11 | /// Type of the RelativeSource.
12 | ///
13 | public ValueType AncestorLevelValueType { get; private set; }
14 | ///
15 | /// Gets the level of ancestor to look for when in mode.
16 | ///
17 | ///
18 | /// Use the default value of 1 to look for the first ancestor of the specified type.
19 | ///
20 | public object? AncestorLevel
21 | {
22 | get { return _ancestorLevel; }
23 | set
24 | {
25 | if (value is int ancestorLevel)
26 | {
27 | if (ancestorLevel <= 0)
28 | throw new ArgumentOutOfRangeException(nameof(value),
29 | "AncestorLevel may not be set to less than 1.");
30 | _ancestorLevel = ancestorLevel;
31 | AncestorLevelValueType = ValueType.Value;
32 | }
33 | else
34 | {
35 | AncestorLevel = value;
36 | AncestorLevelValueType = ValueType.Binding;
37 | }
38 | }
39 | }
40 | ///
41 | /// Type of the RelativeSource.
42 | ///
43 | public ValueType AncestorTypeValueType { get; private set; }
44 |
45 | private object? _ancestorType;
46 |
47 | ///
48 | /// Gets the type of ancestor to look for when in mode.
49 | ///
50 | public object? AncestorType
51 | {
52 | get => _ancestorType;
53 | set
54 | {
55 | if (value is string)
56 | AncestorTypeValueType = ValueType.Value;
57 | else
58 | AncestorTypeValueType = ValueType.Binding;
59 | _ancestorType = value;
60 | }
61 | }
62 | ///
63 | /// Type of the RelativeSource.
64 | ///
65 | public ValueType ModeValueType { get; private set; }
66 |
67 | private object? _mode;
68 | ///
69 | /// Gets or sets a value that describes the type of relative source lookup.
70 | ///
71 | public object? Mode
72 | {
73 | get => _mode;
74 | set
75 | {
76 | if (value is RelativeSourceMode)
77 | ModeValueType = ValueType.Value;
78 | else
79 | ModeValueType = ValueType.Binding;
80 | _mode = value;
81 | }
82 | } //RelativeSourceMode
83 | ///
84 | /// Type of the RelativeSource.
85 | ///
86 | public ValueType TreeValueType { get; private set; }
87 |
88 | private object? _tree;
89 | ///
90 | /// On which tree type the binding should be applied.
91 | ///
92 | public object? Tree
93 | {
94 | get => _tree;
95 | set
96 | {
97 | if (value is TreeType tree)
98 | TreeValueType = ValueType.Value;
99 | else
100 | TreeValueType = ValueType.Binding;
101 | _tree = value;
102 | }
103 | } // TreeType
104 |
105 | }
--------------------------------------------------------------------------------
/BoTech.DesignerForAvalonia/Models/Binding/ValueType.cs:
--------------------------------------------------------------------------------
1 | namespace BoTech.DesignerForAvalonia.Models.Binding;
2 |
3 | public enum ValueType
4 | {
5 | ///
6 | /// When no FallbackValue is defined.
7 | ///
8 | None,
9 | ///
10 | /// When the fallbackvalue is defined through another Binding.
11 | ///
12 | Binding,
13 | ///
14 | /// An direct value assigment => {Binding Text, FallbackValue=Hello}
15 | ///
16 | Value
17 | }
--------------------------------------------------------------------------------
/BoTech.DesignerForAvalonia/Models/Editor/EDragAndDropOperation.cs:
--------------------------------------------------------------------------------
1 | namespace BoTech.DesignerForAvalonia.Models.Editor;
2 |
3 | public enum EDragAndDropOperation
4 | {
5 | None,
6 | DropObjectToPreview,
7 | Paused
8 | }
--------------------------------------------------------------------------------
/BoTech.DesignerForAvalonia/Models/Editor/TreeViewNodeBase.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.ObjectModel;
2 | using BoTech.DesignerForAvalonia.ViewModels.Editor;
3 |
4 | namespace BoTech.DesignerForAvalonia.Models.Editor;
5 | ///
6 | /// Implements some basic functionality for all TreeViewNodes (SolutionExplorer, ViewHierarchy and ItemsExplorer)
7 | ///
8 | public abstract class TreeViewNodeBase
9 | {
10 | ///
11 | /// Will be used by the Search Functionality.
12 | ///
13 | public string Text { get; set; }
14 | public ObservableCollection Children { get; set; } = new ObservableCollection();
15 |
16 | ///
17 | /// This Method search for an Item in the current instance, where the Text Property Contains the given Text.
18 | ///
19 | ///
20 | ///
21 | /// True when any Item was found, else false
22 | public bool Search(string text, TreeViewNodeBase newNode, bool firstIteration = true)
23 | {
24 | if (firstIteration)
25 | {
26 | bool foundInChild = false;
27 | foreach (TreeViewNodeBase child in Children)
28 | if (child.Search(text, newNode, false))
29 | foundInChild = true;
30 | return foundInChild;
31 | }
32 | else
33 | {
34 | TreeViewNodeBase? copy = Copy(this);
35 | if (copy != null)
36 | {
37 | bool found = Text.Contains(text);
38 | bool foundInChild = false;
39 | foreach (TreeViewNodeBase child in Children)
40 | if (child.Search(text, copy, false))
41 | foundInChild = true;
42 | if (found || foundInChild)
43 | {
44 | newNode.Children.Add(copy);
45 | return true;
46 | }
47 | }
48 | }
49 |
50 | return false;
51 | }
52 |
53 | ///
54 | /// Method should Copy the given Node and return the Copy.
55 | ///
56 | ///
57 | ///
58 | protected abstract TreeViewNodeBase? Copy(TreeViewNodeBase nodeToCopy);
59 |
60 | }
--------------------------------------------------------------------------------
/BoTech.DesignerForAvalonia/Models/Project/Binding.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Text.Json.Serialization;
3 | using Avalonia.Controls;
4 | using Avalonia.Data;
5 |
6 | namespace BoTech.DesignerForAvalonia.Models.Project;
7 |
8 | public class Binding
9 | {
10 | ///
11 | /// The string for the Property in the Xml file => "{Binding MyProperty}"
12 | ///
13 | public required string XmlDefinition { get; set; }
14 | ///
15 | /// The Property in the View Model
16 | ///
17 | [JsonIgnore]
18 | public PropertyInfo ViewModelProperty { get; set; }
19 | ///
20 | /// The Property which is defined in the selected control.
21 | ///
22 | [JsonIgnore]
23 | public PropertyInfo ControlPropertyInfo { get; set; }
24 | ///
25 | /// The Binding mode defines the "direction" of a Binding.
26 | ///
27 | public required BindingMode BindingMode { get; set; }
28 | [JsonIgnore]
29 | public Control ControlInstance { get; set; }
30 | [JsonIgnore]
31 | public object LastSourceValue { get; set; } = null;
32 | [JsonIgnore]
33 | public object LastReceiverValue { get; set; } = null;
34 |
35 | }
--------------------------------------------------------------------------------
/BoTech.DesignerForAvalonia/Models/Project/CSharp/ExtractedBindingInfo.cs:
--------------------------------------------------------------------------------
1 | using Avalonia.Data;
2 | using BoTech.DesignerForAvalonia.Models.Binding;
3 |
4 | namespace BoTech.DesignerForAvalonia.Models.Project.CSharp;
5 |
6 | public class ExtractedBindingInfo
7 | {
8 | ///
9 | /// The name of the source property to be bound.
10 | ///
11 | public string Path { get; set; }
12 | ///
13 | /// Type of the Mode.
14 | ///
15 | public ValueType ModeValueType { get; private set; } = ValueType.None;
16 |
17 | private object? _mode;
18 | ///
19 | /// The synchronization direction of the binding.
20 | ///
21 | public object? Mode
22 | {
23 | get => _mode;
24 | set
25 | {
26 | _mode = value;
27 | if(value is BindingMode) ModeValueType = ValueType.Value;
28 | else ModeValueType = ValueType.Binding;
29 | }
30 | }
31 |
32 | ///
33 | /// Priority of the property setter.
34 | ///
35 | public BindingPriority Priority { get; set; }
36 | ///
37 | /// Type of the RelativeSource.
38 | ///
39 | public ValueType RelativeSourceValueType { get; private set; }
40 | ///
41 | /// Describes where the property to which the binding refers can be found.
42 | ///
43 | public ExtractedRelativeSource RelativeSource { get; set; } = new ExtractedRelativeSource();
44 | ///
45 | /// Type of the ElementName.
46 | ///
47 | public ValueType ElementNameValueType { get; private set; } = ValueType.None;
48 |
49 | private object? _elementName;
50 | ///
51 | /// Can be set to the name of another control when the binding refers to a property of this control.
52 | /// For instance: #MyControl.Text and {Binding Text, ElementName=MyControl} are the same.
53 | ///
54 | public object? ElementName
55 | {
56 | get => _elementName;
57 | set
58 | {
59 | _elementName = value;
60 | if(value is string) ElementNameValueType = ValueType.Value;
61 | else ElementNameValueType = ValueType.Binding;
62 | }
63 | }
64 | ///
65 | /// Type of the FallbackValue.
66 | ///
67 | public ValueType FallBackValueType { get; private set; } = ValueType.None;
68 |
69 | private object? _fallbackValue;
70 | ///
71 | /// The Value which will be injected into the property when the referenced property is not reachable or null.
72 | ///
73 | public object? FallbackValue
74 | {
75 | get => _fallbackValue;
76 | set
77 | {
78 | _fallbackValue = value;
79 | if(value is string) FallBackValueType = ValueType.Value;
80 | else FallBackValueType = ValueType.Binding;
81 | }
82 | }
83 | ///
84 | /// Type of the TargetNullValue.
85 | ///
86 | public ValueType TargetNullValueType { get; private set; } = ValueType.None;
87 |
88 | private object? _targetNullValue;
89 | ///
90 | /// Will be applied when the refenced property of this binding is null.
91 | ///
92 | public object? TargetNullValue
93 | {
94 | get => _targetNullValue;
95 | set
96 | {
97 | _targetNullValue = value;
98 | if(value is string) TargetNullValueType = ValueType.Value;
99 | else TargetNullValueType = ValueType.Binding;
100 | }
101 | }
102 | ///
103 | /// Type of the UpdateSourceTrigger.
104 | ///
105 | public ValueType UpdateSourceTriggerValueType { get; private set; } = ValueType.None;
106 |
107 | private object? _updateSourceTrigger;
108 | ///
109 | /// Set when the binding should be updated.
110 | /// NOTE: Some parts may not have supported in this Version. For Instance Explicit.
111 | ///
112 | public object UpdateSourceTrigger
113 | {
114 | get => _updateSourceTrigger;
115 | set
116 | {
117 | _updateSourceTrigger = value;
118 | if(value is string) UpdateSourceTriggerValueType = ValueType.Value;
119 | else UpdateSourceTriggerValueType = ValueType.Binding;
120 | }
121 | }
122 |
123 | }
124 |
125 |
126 |
--------------------------------------------------------------------------------
/BoTech.DesignerForAvalonia/Models/Project/CSharp/ExtractedClassInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Text.Json.Serialization;
3 |
4 | namespace BoTech.DesignerForAvalonia.Models.Project.CSharp;
5 |
6 | public class ExtractedClassInfo
7 | {
8 | ///
9 | /// The Classname of this Class
10 | ///
11 | public string ClassName { get; set; }
12 | ///
13 | /// The xml Documentation
14 | ///
15 | public string Documentation { get; set; } = string.Empty;
16 | ///
17 | /// The full namespace of this Class.
18 | ///
19 | public string Namespace { get; set; }
20 | ///
21 | /// All declared Methods in this class
22 | ///
23 | public List Methods { get; set; } = new List();
24 | ///
25 | /// All declared Properties in this Class.
26 | ///
27 | public List Properties { get; set; } = new List();
28 | ///
29 | /// All Classes that are defined within this Class.
30 | ///
31 | public List SubClasses { get; set; } = new List();
32 | ///
33 | /// If an exception is thrown during the parsing process, the error text can be stored here.
34 | ///
35 | [JsonIgnore]
36 | public string ParseError { get; set; } = string.Empty;
37 | }
--------------------------------------------------------------------------------
/BoTech.DesignerForAvalonia/Models/Project/CSharp/ExtractedMethodInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Text.Json.Serialization;
3 |
4 | namespace BoTech.DesignerForAvalonia.Models.Project.CSharp;
5 |
6 | public class ExtractedMethodInfo
7 | {
8 | ///
9 | /// The Name of the Method
10 | ///
11 | public required string Name { get; set; }
12 | ///
13 | /// Return Type name with namespace if necessary
14 | ///
15 | public string ReturnType { get; set; } = "void";
16 | ///
17 | /// The xml Documentation
18 | ///
19 | public string Documentation { get; set; } = string.Empty;
20 | ///
21 | /// All Parameters of the Method
22 | ///
23 | public List Parameters { get; set; } = new List();
24 | ///
25 | /// If an exception is thrown during the parsing process, the error text can be stored here.
26 | ///
27 | [JsonIgnore]
28 | public string ParseError { get; set; } = string.Empty;
29 | }
30 |
31 | public class ExtractedParamInfo
32 | {
33 | ///
34 | /// The name of the Parameter
35 | ///
36 | public required string Name { get; set; }
37 | ///
38 | /// Type name with namespace if necessary
39 | ///
40 | public required string Type { get; set; }
41 | ///
42 | /// Type name with namespace if necessary
43 | ///
44 | public required string DefaultValue { get; set; }
45 | ///
46 | /// extracted Documentation of the Method documentation
47 | ///
48 | public required string Documentation { get; set; }
49 | ///
50 | /// If an exception is thrown during the parsing process, the error text can be stored here.
51 | ///
52 | [JsonIgnore]
53 | public string ParseError { get; set; } = string.Empty;
54 | }
--------------------------------------------------------------------------------
/BoTech.DesignerForAvalonia/Models/Project/CSharp/ExtractedPropertyInfo.cs:
--------------------------------------------------------------------------------
1 |
2 | using System.Text.Json.Serialization;
3 |
4 | namespace BoTech.DesignerForAvalonia.Models.Project.CSharp;
5 |
6 | public class ExtractedPropertyInfo
7 | {
8 | ///
9 | /// The Name of the Property
10 | ///
11 | public string Name { get; set; }
12 | ///
13 | /// The XML Documentation
14 | ///
15 | public string Documentation { get; set; } = string.Empty;
16 | ///
17 | /// The Type with Namespace if necessary
18 | ///
19 | public string Type { get; set; }
20 | ///
21 | /// The AccessModifier of the Property
22 | ///
23 | public Modifier AccessModifier { get; set; } = Modifier.Public;
24 | ///
25 | /// When the Property is defined with the keyword static
26 | ///
27 | public bool IsStatic { get; set; } = false;
28 | ///
29 | /// When the property is defined with the keyword constant
30 | ///
31 | public bool IsConstant { get; set; } = false;
32 | ///
33 | /// When the Property is defined with the keyword readonly
34 | ///
35 | public bool IsReadOnly { get; set; } = false;
36 | ///
37 | /// The definition of the default value. For Example "new User("Florian");"
38 | ///
39 | public string DefaultValue { get; set; } = string.Empty;
40 | ///
41 | /// When a Getter is defined in the brackets => {get;}
42 | ///
43 | public bool HasGetter { get; set; } = false;
44 | ///
45 | /// When a Setter is defined in the brackets => {set;}
46 | ///
47 | public bool HasSetter { get; set; } = false;
48 | ///
49 | /// If an exception is thrown during the parsing process, the error text can be stored here.
50 | ///
51 | [JsonIgnore]
52 | public string ParseError { get; set; } = string.Empty;
53 |
54 | }
--------------------------------------------------------------------------------
/BoTech.DesignerForAvalonia/Models/Project/CSharp/Modifier.cs:
--------------------------------------------------------------------------------
1 | namespace BoTech.DesignerForAvalonia.Models.Project.CSharp;
2 |
3 | public enum Modifier
4 | {
5 | Public,
6 | Protected,
7 | Internal,
8 | Private,
9 | }
--------------------------------------------------------------------------------
/BoTech.DesignerForAvalonia/Models/Project/DisplayableProjectInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reactive;
2 | using BoTech.DesignerForAvalonia.ViewModels;
3 | using ReactiveUI;
4 |
5 | namespace BoTech.DesignerForAvalonia.Models.Project;
6 | ///
7 | /// This class can be used to show the Project label on the first view.
8 | ///
9 | public class DisplayableProjectInfo
10 | {
11 |
12 | public bool Red { get; set; } = true;
13 | public bool Pink { get; set; } = false;
14 | public bool Purple { get; set; } = false;
15 | public bool Violet { get; set; } = false;
16 | public bool Indigo { get; set; } = false;
17 | public bool Blue { get; set; } = false;
18 | public bool LightBlue { get; set; } = false;
19 | public bool Cyan { get; set; } = false;
20 | public bool Teal { get; set; } = false;
21 | public bool Green { get; set; } = false;
22 | public bool LightGreen { get; set; } = false;
23 | public bool Lime { get; set; } = false;
24 | public bool Yellow { get; set; } = false;
25 | public bool Amber { get; set; } = false;
26 | public bool Orange { get; set; } = false;
27 | public bool Grey { get; set; } = false;
28 | public bool White { get; set; } = false;
29 |
30 | public void SetColorByName(string colorName)
31 | {
32 | SetAllToLow();
33 | switch (colorName)
34 | {
35 | case "Red":
36 | Red = true;
37 | break;
38 | case "Pink":
39 | Pink = true;
40 | break;
41 | case "Purple":
42 | Purple = true;
43 | break;
44 | case "Violet":
45 | Violet = true;
46 | break;
47 | case "Indigo":
48 | Indigo = true;
49 | break;
50 | case "Blue":
51 | Blue = true;
52 | break;
53 | case "Cyan":
54 | Cyan = true;
55 | break;
56 | case "Teal":
57 | Teal = true;
58 | break;
59 | case "Green":
60 | Green = true;
61 | break;
62 | case "Lime":
63 | Lime = true;
64 | break;
65 | case "Yellow":
66 | Yellow = true;
67 | break;
68 | case "Amber":
69 | Amber = true;
70 | break;
71 | case "Orange":
72 | Orange = true;
73 | break;
74 | case "Grey":
75 | Grey = true;
76 | break;
77 | case "White":
78 | White = true;
79 | break;
80 | }
81 | }
82 |
83 | private void SetAllToLow()
84 | {
85 | Red = false;
86 | Pink = false;
87 | Purple = false;
88 | Violet = false;
89 | Indigo = false;
90 | Blue = false;
91 | LightBlue = false;
92 | Cyan = false;
93 | Teal = false;
94 | Green = false;
95 | LightGreen = false;
96 | Lime = false;
97 | Yellow = false;
98 | Grey = false;
99 | White = false;
100 | }
101 |
102 | }
--------------------------------------------------------------------------------
/BoTech.DesignerForAvalonia/Models/Project/OpenableProject.cs:
--------------------------------------------------------------------------------
1 | using System.Reactive;
2 | using BoTech.DesignerForAvalonia.ViewModels;
3 | using ReactiveUI;
4 |
5 | namespace BoTech.DesignerForAvalonia.Models.Project;
6 | ///
7 | /// This class implementes the LoadRecentProjectCommand
8 | ///
9 | public class OpenableProject : Project
10 | {
11 | ///
12 | /// Command for the ItemsControl at the Project start Page
13 | ///
14 | public ReactiveCommand LoadRecentProjectCommand { get; set; }
15 |
16 | public OpenableProject(ProjectStartViewModel viewModel, Project project, bool disable = false)
17 | {
18 | // Copy all Properties of base class
19 | this.SolutionFilePath = project.SolutionFilePath;
20 | this.OutputPath = project.OutputPath;
21 | this.LastUsed = project.LastUsed;
22 | this.Name = project.Name;
23 | this.Views = project.Views;
24 | this.ViewModelPath = project.ViewModelPath;
25 | this.SolutionFile = project.SolutionFile;
26 | this.ViewPath = project.ViewPath;
27 | this.ShortName = project.ShortName;
28 | this.DisplayableProjectInfo = project.DisplayableProjectInfo;
29 | if (!disable)
30 | {
31 | LoadRecentProjectCommand = ReactiveCommand.Create(() => { viewModel.LoadOpenableProject(this); });
32 | }
33 | }
34 | }
--------------------------------------------------------------------------------
/BoTech.DesignerForAvalonia/Models/Project/Project.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Reflection;
4 | using System.Text.Json.Serialization;
5 | using Microsoft.Build.Construction;
6 |
7 | namespace BoTech.DesignerForAvalonia.Models.Project;
8 |
9 | public class Project
10 | {
11 | ///
12 | /// The Path to the .sln File.
13 | ///
14 | public string SolutionFilePath { get; set; } = string.Empty;
15 | ///
16 | /// The Model which contains Information about the Solution File. For example, it contains all defined Projects in the Solution.
17 | ///
18 | [JsonIgnore]
19 | public SolutionFile SolutionFile { get; set; }
20 | ///
21 | /// The Name of the Solution
22 | ///
23 | public string Name { get; set; } = string.Empty;
24 | ///
25 | /// A Short name which will be displayed in a Rounded Colored rectangle.
26 | ///
27 | public string ShortName { get; set; } = string.Empty;
28 | ///
29 | /// The Date and Time when the project was opened.
30 | ///
31 | public DateTime LastUsed { get; set; }
32 | ///
33 | /// The complete Path to the ViewModel folder.
34 | ///
35 | public string ViewModelPath { get; set; } = string.Empty;
36 | ///
37 | /// The complete Path to the Views folder.
38 | ///
39 | public string ViewPath { get; set; } = string.Empty;
40 | ///
41 | /// Saves the Path to the prebuilt assemblies, which contains all Classes and Views of the Project, so that they can be instantiated.
42 | ///
43 | public string OutputPath { get; set; } = string.Empty;
44 |
45 | ///
46 | /// The Library which contains all compiled classes of the solution.
47 | ///
48 | [JsonIgnore]
49 | public Assembly Assembly { get; set; } = null;
50 | ///
51 | /// All Views that the Project contains. By default, this will be the MainView and the MainWindow.
52 | ///
53 | public List Views { get; set; } = new List();
54 | ///
55 | /// All Views that the Project contains. By default, this will be the MainViewModel.
56 | ///
57 | public List ViewModels { get; set; } = new List();
58 | ///
59 | /// A simple Model which provides Information about the Label Color
60 | ///
61 | public DisplayableProjectInfo DisplayableProjectInfo { get; set; } = new DisplayableProjectInfo();
62 |
63 | }
--------------------------------------------------------------------------------
/BoTech.DesignerForAvalonia/Models/Project/ProjectView.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text.Json.Serialization;
4 | using BoTech.DesignerForAvalonia.Models.Project.CSharp;
5 |
6 | namespace BoTech.DesignerForAvalonia.Models.Project;
7 |
8 | public class ProjectView
9 | {
10 | ///
11 | /// Name of the View
12 | ///
13 | public string Name { get; set; }
14 | ///
15 | /// Complete Path to the .axaml File
16 | ///
17 | public string PathToView { get; set; }
18 | ///
19 | /// Complete Path to the .axaml.cs File
20 | ///
21 | public string PathToCodeBehind { get; set; }
22 | ///
23 | /// The ViewModel which is selected in the .axaml file.
24 | ///
25 | public ProjectViewModel ViewModel { get; set; } = null;
26 | ///
27 | /// All Bindings defined in this View.
28 | ///
29 | public List Bindings { get; set; } = new List();
30 | ///
31 | /// The parsed information from the .cs source File.
32 | ///
33 | [JsonIgnore]
34 | public ExtractedClassInfo? ClassInfoFromFile { get; set; }
35 | ///
36 | /// Is true when all members, functions that are located in the Source File are also defined in the Assembly.
37 | ///
38 | [JsonIgnore]
39 | public bool IsAssemblyEqualsToSource { get; set; }
40 |
41 |
42 | }
--------------------------------------------------------------------------------
/BoTech.DesignerForAvalonia/Models/Project/ProjectViewModel.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Reflection;
3 | using System.Text.Json.Serialization;
4 | using BoTech.DesignerForAvalonia.Models.Project.CSharp;
5 |
6 |
7 | namespace BoTech.DesignerForAvalonia.Models.Project;
8 | ///
9 | /// Stores all important information for an ViewModel.
10 | ///
11 | public class ProjectViewModel
12 | {
13 | ///
14 | /// The absolute Path to the ViewModel
15 | ///
16 | public required string Path { get; set; }
17 | ///
18 | /// The Name of the class
19 | ///
20 | public required string Name { get; set; }
21 | ///
22 | /// The full namespace of the class with the same Name as the File. The classname is included.
23 | ///
24 | public string Namespace { get; set; } = string.Empty;
25 | ///
26 | /// The parsed information from the .cs source File.
27 | ///
28 | [JsonIgnore]
29 | public ExtractedClassInfo? ClassInfoFromFile { get; set; }
30 | ///
31 | /// Is true when all members, functions that are located in the Source File are also defined in the Assembly.
32 | ///
33 | [JsonIgnore]
34 | public bool IsAssemblyEqualsToSource { get; set; }
35 |
36 | }
--------------------------------------------------------------------------------
/BoTech.DesignerForAvalonia/Models/XML/XmlControl.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Reflection;
5 | using System.Xml;
6 | using Avalonia.Controls;
7 | using BoTech.DesignerForAvalonia.Services.Avalonia;
8 |
9 | namespace BoTech.DesignerForAvalonia.Models.XML;
10 | ///
11 | /// This Model connects an XmlNode with a Control.
12 | /// This is necessary for the serialization Process where old XmlNodes may be edited.
13 | ///
14 | public class XmlControl : ICloneable
15 | {
16 | public XmlControl? Parent { get; set; }
17 | public List Children { get; set; } = new List();
18 | public Control Control { get; set; }
19 | public XmlNode Node { get; set; }
20 | ///
21 | /// Searches in every Child for the given Control and returns itself.
22 | ///
23 | ///
24 | /// Returns null when nothing found otherwise itself
25 | public XmlControl? Find(Control control)
26 | {
27 | if (control == Control)
28 | {
29 | return this;
30 | }
31 | XmlControl? xmlControl = null;
32 | foreach (XmlControl child in Children)
33 | {
34 | if ((xmlControl = child.Find(control)) != null)
35 | {
36 | return xmlControl;
37 | }
38 | }
39 | return null;
40 | }
41 | ///
42 | /// Searches in every Child for the given node and returns itself.
43 | ///
44 | ///
45 | /// Returns null when nothing found otherwise itself.
46 | public XmlControl Find(XmlNode node)
47 | {
48 | if (node == Node)
49 | {
50 | return this;
51 | }
52 | XmlControl? xmlControl = null;
53 | foreach (XmlControl child in Children)
54 | {
55 | if ((xmlControl = child.Find(node)) != null)
56 | {
57 | return xmlControl;
58 | }
59 | }
60 | return null;
61 | }
62 | ///
63 | /// Gets the most Parent Control.
64 | ///
65 | ///
66 | public XmlControl GetMostParent()
67 | {
68 | if(Parent != null) return Parent.GetMostParent();
69 | return this;
70 | }
71 | ///
72 | /// Clone the object: Method clones all Properties of the Control and inject it into a new Control.
73 | /// It also only copies all Attributes of the XmlNode into a new XmlNode.
74 | ///
75 | ///
76 | public object Clone()
77 | {
78 | XmlControl xmlControlCopy = new XmlControl();
79 |
80 | // Create a "deep Copy" of the Control by using the XmlNode.
81 |
82 | Control? copiedControl = Activator.CreateInstance(this.Control.GetType()) as Control;
83 | if (copiedControl != null)
84 | {
85 | // We want to iterate through the Attribute List to only copy the Properties that have really changed.
86 | if (this.Node.Attributes != null)
87 | {
88 | foreach (XmlAttribute attribute in this.Node.Attributes)
89 | {
90 | PropertyInfo? propertyInfo = copiedControl.GetType().GetProperty(attribute.Name);
91 | if (propertyInfo != null)
92 | {
93 | // Get the Property of the Current Control and Clone it
94 |
95 | // propertyInfo.SetValue(copiedControl, propertyInfo.GetValue(this.Node.Attributes[attribute.Name], null));
96 | if (propertyInfo.PropertyType.IsEnum)
97 | {
98 | propertyInfo.SetValue(copiedControl,
99 | Enum.Parse(propertyInfo.PropertyType, attribute.Value));
100 | }
101 | else
102 | {
103 | propertyInfo.SetValue(copiedControl, CloneService.CloneProperty(propertyInfo, copiedControl, Control));
104 |
105 | }
106 | }
107 | }
108 | }
109 | xmlControlCopy.Control = copiedControl;
110 | }
111 |
112 | // Creating a Copy of the Node
113 |
114 | xmlControlCopy.Node = Node.CloneNode(true);
115 |
116 | return xmlControlCopy;
117 | }
118 |
119 | }
--------------------------------------------------------------------------------
/BoTech.DesignerForAvalonia/Services/Avalonia/CloneService.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Reflection;
5 |
6 | namespace BoTech.DesignerForAvalonia.Services.Avalonia;
7 |
8 | public class CloneService
9 | {
10 | public static object CloneProperty(PropertyInfo propertyInfo, object copy, object original)
11 | {
12 | // Cloning the Property
13 | if (HasTypeConstructorWithNoParams(propertyInfo.PropertyType))
14 | {
15 | // Cloning all Properties:
16 | PropertyInfo[] properties = copy.GetType().GetProperties();
17 | List originalProperties = original.GetType().GetProperties().ToList();
18 | foreach (PropertyInfo property in properties)
19 | {
20 | // When it is a primitive Type we can use the Parse Method of the primitive type to copy it
21 | if (property.PropertyType.IsPrimitive)
22 | {
23 | PropertyInfo? originalProperty = originalProperties.Find(p => p.Name == property.Name);
24 | if (originalProperty != null && originalProperty.GetValue(original) != null)
25 | {
26 | string originalString = originalProperty.GetValue(original).ToString();
27 | switch (propertyInfo.PropertyType.Name)
28 | {
29 | case "Boolean":
30 | property.SetValue(copy, Boolean.Parse(originalString));
31 | break;
32 | case "Byte":
33 | property.SetValue(copy, Byte.Parse(originalString));
34 | break;
35 | case "SByte":
36 | property.SetValue(copy, SByte.Parse(originalString));
37 | break;
38 | case "Char":
39 | property.SetValue(copy, Char.Parse(originalString));
40 | break;
41 | case "Decimal":
42 | property.SetValue(copy, Decimal.Parse(originalString));
43 | break;
44 | case "Double":
45 | property.SetValue(copy, Double.Parse(originalString));
46 | break;
47 | case "Single":
48 | property.SetValue(copy, Char.Parse(originalString));
49 | break;
50 | case "Int32":
51 | property.SetValue(copy, Int32.Parse(originalString));
52 | break;
53 | case "UInt32":
54 | property.SetValue(copy, UInt32.Parse(originalString));
55 | break;
56 | case "IntPtr":
57 | property.SetValue(copy, IntPtr.Parse(originalString));
58 | break;
59 | case "UIntPtr":
60 | property.SetValue(copy, UIntPtr.Parse(originalString));
61 | break;
62 | case "Int64":
63 | property.SetValue(copy, Int64.Parse(originalString));
64 | break;
65 | case "UInt64":
66 | property.SetValue(copy, UInt64.Parse(originalString));
67 | break;
68 | case "Int16":
69 | property.SetValue(copy, Int16.Parse(originalString));
70 | break;
71 | case "UInt16":
72 | property.SetValue(copy, UInt16.Parse(originalString));
73 | break;
74 | }
75 | }
76 | }
77 | else
78 | {
79 | // Go step deeper until the Property is a primitive.
80 | property.SetValue(copy, CloneProperty(property, copy, original));
81 | }
82 | }
83 | return copy;
84 | }
85 |
86 | // TODO: Copy all Types which have params in the constructors
87 | //ExecuteCloneThroughTheCtor(propertyInfo, copy, original);
88 | // For now just return null to short up the development cycle
89 | return null;
90 | }
91 | ///
92 | /// Checks if the given Type has a constructor which does not contain any params in it definition.
93 | ///
94 | ///
95 | ///
96 | private static bool HasTypeConstructorWithNoParams(Type type)
97 | {
98 | foreach (ConstructorInfo ctor in type.GetConstructors())
99 | {
100 | if(ctor.GetParameters().Length == 0) return true;
101 | }
102 | return false;
103 | }
104 | ///
105 | /// Make a deep copy by searching for the Properties which are needed to invoke the Constructor.
106 | /// For Instance when the given Type is Thickness. The Thickness class has the Properties Bottom, Left, Right and Top and a constructor (Thickness(double left, double top, double right, double bottom).
107 | ///
108 | ///
109 | ///
110 | ///
111 | private static void ExecuteCloneThroughTheCtor(PropertyInfo propertyInfo, object copy, object original)
112 | {
113 | // Search for the Constructor where all params exists as Properties in the Type
114 | foreach (ConstructorInfo constructor in propertyInfo.PropertyType.GetConstructors())
115 | {
116 | List propertyInfos = propertyInfo.PropertyType.GetProperties().ToList();
117 | List