mirror of
https://onedev.site.tesses.net/crosslang/crosslangdevstudio
synced 2026-02-08 09:15:45 +00:00
First Commit
This commit is contained in:
65
ViewModels/FileEditorViewModel.cs
Normal file
65
ViewModels/FileEditorViewModel.cs
Normal file
@@ -0,0 +1,65 @@
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Platform.Storage;
|
||||
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using CrossLangDevStudio.Messages;
|
||||
using CrossLangDevStudio.Views;
|
||||
|
||||
namespace CrossLangDevStudio.ViewModels;
|
||||
|
||||
public partial class FileEditorViewModel : ViewModelBase, ISavable
|
||||
{
|
||||
TabItemViewModel tab;
|
||||
public string FilePath { get; }
|
||||
bool _modified = false;
|
||||
private bool Modified
|
||||
{
|
||||
get => _modified;
|
||||
set
|
||||
{
|
||||
_modified = value;
|
||||
|
||||
if (value)
|
||||
{
|
||||
tab.Header = $"{Path.GetFileName(FilePath)}*";
|
||||
}
|
||||
else
|
||||
{
|
||||
tab.Header = Path.GetFileName(FilePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private string _text = "";
|
||||
|
||||
public string Text
|
||||
{
|
||||
get => _text;
|
||||
set
|
||||
{
|
||||
|
||||
Modified = true;
|
||||
this.SetProperty(ref _text, value, nameof(Text));
|
||||
}
|
||||
}
|
||||
|
||||
public FileEditorViewModel(string path,TabItemViewModel tab)
|
||||
{
|
||||
this.tab = tab;
|
||||
FilePath = path;
|
||||
_text = File.ReadAllText(path);
|
||||
}
|
||||
|
||||
public void Save()
|
||||
{
|
||||
File.WriteAllText(FilePath, Text);
|
||||
Modified = false;
|
||||
}
|
||||
}
|
||||
5
ViewModels/ISavable.cs
Normal file
5
ViewModels/ISavable.cs
Normal file
@@ -0,0 +1,5 @@
|
||||
namespace CrossLangDevStudio.ViewModels;
|
||||
interface ISavable
|
||||
{
|
||||
void Save();
|
||||
}
|
||||
409
ViewModels/MainWindowViewModel.cs
Normal file
409
ViewModels/MainWindowViewModel.cs
Normal file
@@ -0,0 +1,409 @@
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Platform.Storage;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using CrossLangDevStudio.Messages;
|
||||
using CrossLangDevStudio.Models;
|
||||
using CrossLangDevStudio.Views;
|
||||
|
||||
namespace CrossLangDevStudio.ViewModels;
|
||||
|
||||
public partial class MainWindowViewModel : ViewModelBase
|
||||
{
|
||||
|
||||
public HttpClient Client { get; set; } = new();
|
||||
public string CurrentProject { get; set; } = "";
|
||||
public Func<object> NewItemFactory => AddItem;
|
||||
|
||||
|
||||
public ObservableCollection<TabItemViewModel> TabItems { get; } = new();
|
||||
public ObservableCollection<ProjectFileNode> ProjectFiles { get; } = new ObservableCollection<ProjectFileNode>();
|
||||
|
||||
public EventHandler<Tabalonia.Events.CloseLastTabEventArgs>? Closed { get; } = null;
|
||||
|
||||
public TabItemViewModel WelcomePage
|
||||
{
|
||||
get
|
||||
{
|
||||
return new TabItemViewModel()
|
||||
{
|
||||
Header = "Welcome",
|
||||
Body = new WelcomeViewModel(this)
|
||||
};
|
||||
}
|
||||
}
|
||||
private ProjectFileNode? _selectedProjectFile = null;
|
||||
|
||||
public ProjectFileNode? SelectedProjectFile
|
||||
{
|
||||
get => _selectedProjectFile;
|
||||
set
|
||||
{
|
||||
_selectedProjectFile = value;
|
||||
value?.Click?.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public MainWindowViewModel(string[] args)
|
||||
{
|
||||
if (args.Length == 1)
|
||||
{
|
||||
LoadProject(args[0]);
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(CurrentProject))
|
||||
this.TabItems.Add(WelcomePage);
|
||||
}
|
||||
|
||||
|
||||
private object AddItem()
|
||||
{
|
||||
var tab = new TabItemViewModel
|
||||
{
|
||||
Header = "New Tab",
|
||||
|
||||
};
|
||||
if (Directory.Exists(CurrentProject))
|
||||
{
|
||||
var newTabItem = new NewTabViewModel(this, tab);
|
||||
tab.Body = newTabItem;
|
||||
}
|
||||
|
||||
|
||||
|
||||
return tab;
|
||||
}
|
||||
|
||||
internal void LoadProject(string obj)
|
||||
{
|
||||
if (!File.Exists(Path.Combine(obj, "cross.json")))
|
||||
{
|
||||
return;
|
||||
}
|
||||
CrossLangShell.EnsureRecent(obj);
|
||||
CurrentProject = obj.TrimEnd(Path.DirectorySeparatorChar);
|
||||
Refresh(CurrentProject);
|
||||
}
|
||||
[RelayCommand]
|
||||
public void RefreshListing()
|
||||
{
|
||||
if (!File.Exists(Path.Combine(CurrentProject, "cross.json")))
|
||||
{
|
||||
return;
|
||||
}
|
||||
Refresh(CurrentProject);
|
||||
}
|
||||
|
||||
private void Refresh(string obj)
|
||||
{
|
||||
|
||||
|
||||
|
||||
for (int i = 0; i < TabItems.Count; i++)
|
||||
{
|
||||
if (TabItems[i].Body is WelcomeViewModel)
|
||||
{
|
||||
TabItems.RemoveAt(i);
|
||||
i--;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ObservableCollection<ProjectFileNode> entries = new ObservableCollection<ProjectFileNode>
|
||||
{
|
||||
new ProjectFileNode("Project",[
|
||||
new ProjectFileNode("Configuration",()=>{
|
||||
|
||||
OpenProjectConfig();
|
||||
}),
|
||||
new ProjectFileNode("Packages")
|
||||
])
|
||||
|
||||
};
|
||||
|
||||
void Itterate(ObservableCollection<ProjectFileNode> nodes, string dir)
|
||||
{
|
||||
|
||||
foreach (var item in Directory.EnumerateDirectories(dir))
|
||||
{
|
||||
ObservableCollection<ProjectFileNode> files = new();
|
||||
Itterate(files, item);
|
||||
var pfn = new ProjectFileNode(Path.GetFileName(item), files);
|
||||
nodes.Add(pfn);
|
||||
}
|
||||
foreach (var item in Directory.EnumerateFiles(dir))
|
||||
{
|
||||
nodes.Add(new ProjectFileNode(Path.GetFileName(item), () =>
|
||||
{
|
||||
OpenFile(item);
|
||||
}));
|
||||
}
|
||||
|
||||
}
|
||||
Itterate(entries, obj);
|
||||
ProjectFiles.Clear();
|
||||
ProjectFiles.Add(new ProjectFileNode(Path.GetFileName(obj), entries));
|
||||
}
|
||||
|
||||
private void OpenProjectConfig()
|
||||
{
|
||||
|
||||
if (Directory.Exists(CurrentProject))
|
||||
{
|
||||
var config = Path.Combine(CurrentProject, "cross.json");
|
||||
foreach (var item in TabItems)
|
||||
{
|
||||
if (item.Body is ProjectConfigurationViewModel model && model.FilePath == config)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
TabItemViewModel vm = new TabItemViewModel();
|
||||
vm.Header = "Project Configuration";
|
||||
var pcm = new ProjectConfigurationViewModel(config, vm);
|
||||
|
||||
vm.Body = pcm;
|
||||
|
||||
AddTab(vm);
|
||||
}
|
||||
}
|
||||
|
||||
static string[] FILE_EXTS = new string[]{
|
||||
".tcross",
|
||||
".json",
|
||||
".txt",
|
||||
".cpp",
|
||||
".hpp",
|
||||
".html",
|
||||
".css",
|
||||
".webmanifest",
|
||||
".cs",
|
||||
".c",
|
||||
".h",
|
||||
".xml",
|
||||
".xaml",
|
||||
".js",
|
||||
".jsx",
|
||||
".ts",
|
||||
".tsx",
|
||||
".gitignore",
|
||||
".svg"
|
||||
};
|
||||
|
||||
public void OpenFile(string path)
|
||||
{
|
||||
bool isValid = false;
|
||||
foreach (var item in FILE_EXTS)
|
||||
{
|
||||
if (Path.GetExtension(path).ToLower() == item)
|
||||
isValid = true;
|
||||
}
|
||||
if (!isValid) return;
|
||||
|
||||
foreach (var item in TabItems)
|
||||
{
|
||||
if (item.Body is FileEditorViewModel model)
|
||||
{
|
||||
if (model.FilePath == path)
|
||||
{
|
||||
SelectedTab = item;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
var tab = new TabItemViewModel
|
||||
{
|
||||
Header = Path.GetFileName(path),
|
||||
|
||||
};
|
||||
tab.Body = new FileEditorViewModel(path,tab);
|
||||
AddTab(tab);
|
||||
}
|
||||
|
||||
[ObservableProperty]
|
||||
private TabItemViewModel? _selectedTab = null;
|
||||
private void AddTab(TabItemViewModel item)
|
||||
{
|
||||
TabItems.Add(item);
|
||||
SelectedTab = item;
|
||||
|
||||
}
|
||||
[RelayCommand]
|
||||
public async Task NewProjectAsync()
|
||||
{
|
||||
var res = await WeakReferenceMessenger.Default.Send(new NewProjectMessage());
|
||||
if (!string.IsNullOrWhiteSpace(res))
|
||||
{
|
||||
LoadProject(res);
|
||||
}
|
||||
}
|
||||
[RelayCommand]
|
||||
public async Task OpenProjectAsync()
|
||||
{
|
||||
var opts = new FolderPickerOpenOptions();
|
||||
opts.AllowMultiple = false;
|
||||
opts.Title = "Open Project";
|
||||
|
||||
var window = await WeakReferenceMessenger.Default.Send(new GetWindowMessage());
|
||||
opts.SuggestedStartLocation = await window.StorageProvider.TryGetFolderFromPathAsync(CrossLangShell.Settings.ProjectDirectory) ?? null;
|
||||
var res = await window.StorageProvider.OpenFolderPickerAsync(opts);
|
||||
if (res.Count == 1)
|
||||
{
|
||||
var url = res[0].TryGetLocalPath();
|
||||
if (!string.IsNullOrWhiteSpace(url))
|
||||
{
|
||||
LoadProject(url);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void OpenProjectInFileManager()
|
||||
{
|
||||
if (Directory.Exists(CurrentProject))
|
||||
{
|
||||
CrossLangShell.OpenFolderInFileManager(CurrentProject);
|
||||
}
|
||||
}
|
||||
[RelayCommand]
|
||||
private void OpenProjectInTerminal()
|
||||
{
|
||||
if (Directory.Exists(CurrentProject))
|
||||
{
|
||||
CrossLangShell.OpenTerminalInFolder(CurrentProject);
|
||||
}
|
||||
}
|
||||
[RelayCommand]
|
||||
private void BuildAndRun()
|
||||
{
|
||||
SaveAll();
|
||||
if (Directory.Exists(CurrentProject))
|
||||
{
|
||||
CrossLangShell.RunProjectInFolder(CurrentProject);
|
||||
}
|
||||
}
|
||||
[RelayCommand]
|
||||
private void Build()
|
||||
{
|
||||
SaveAll();
|
||||
if (Directory.Exists(CurrentProject))
|
||||
{
|
||||
CrossLangShell.BuildProjectInFolder(CurrentProject);
|
||||
}
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void Save()
|
||||
{
|
||||
SelectedTab?.Save();
|
||||
}
|
||||
[RelayCommand]
|
||||
private void SaveAll()
|
||||
{
|
||||
foreach (var tab in TabItems)
|
||||
{
|
||||
tab.Save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public partial class NewTabViewModel : ViewModelBase
|
||||
{
|
||||
private MainWindowViewModel mainWindowViewModel;
|
||||
private TabItemViewModel tab;
|
||||
|
||||
public NewTabViewModel(MainWindowViewModel mainWindowViewModel, TabItemViewModel tab)
|
||||
{
|
||||
this.mainWindowViewModel = mainWindowViewModel;
|
||||
this.tab = tab;
|
||||
}
|
||||
|
||||
[ObservableProperty]
|
||||
private string _filePath = "src/";
|
||||
|
||||
[ObservableProperty]
|
||||
private decimal _progress = 0;
|
||||
|
||||
[ObservableProperty]
|
||||
private string _url = "";
|
||||
|
||||
[RelayCommand]
|
||||
private void CreateDirectory()
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(FilePath))
|
||||
{
|
||||
Directory.CreateDirectory(Path.Combine(mainWindowViewModel.CurrentProject, FilePath));
|
||||
mainWindowViewModel.RefreshListing();
|
||||
mainWindowViewModel.TabItems.Remove(tab);
|
||||
}
|
||||
}
|
||||
[RelayCommand]
|
||||
private void CreateFile()
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(FilePath))
|
||||
{
|
||||
var path = Path.Combine(mainWindowViewModel.CurrentProject, FilePath);
|
||||
File.WriteAllText(path, "");
|
||||
mainWindowViewModel.RefreshListing();
|
||||
mainWindowViewModel.TabItems.Remove(tab);
|
||||
mainWindowViewModel.OpenFile(path);
|
||||
}
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private async Task DownloadFileAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
using var destStrm = File.Create(Path.Combine(mainWindowViewModel.CurrentProject, FilePath));
|
||||
var res = await mainWindowViewModel.Client.GetAsync(Url);
|
||||
long length = 0;
|
||||
long offset = 0;
|
||||
Progress = 0;
|
||||
if (res.IsSuccessStatusCode)
|
||||
{
|
||||
if (res.Content.Headers.ContentLength.HasValue)
|
||||
{
|
||||
length = res.Content.Headers.ContentLength.Value;
|
||||
byte[] array = new byte[1024];
|
||||
int read = 0;
|
||||
using var src = await res.Content.ReadAsStreamAsync();
|
||||
do
|
||||
{
|
||||
read = await src.ReadAsync(array);
|
||||
await destStrm.WriteAsync(array, 0, read);
|
||||
offset += read;
|
||||
if (length > 0)
|
||||
{
|
||||
Progress = (decimal)offset / (decimal)length;
|
||||
}
|
||||
|
||||
} while (read != 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
await res.Content.CopyToAsync(destStrm);
|
||||
}
|
||||
Progress = 1;
|
||||
mainWindowViewModel.RefreshListing();
|
||||
mainWindowViewModel.TabItems.Remove(tab);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
File.Delete(FilePath);
|
||||
this.Url = $"FAILED: {this.Url}";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
120
ViewModels/NewProjectDialogViewModel.cs
Normal file
120
ViewModels/NewProjectDialogViewModel.cs
Normal file
@@ -0,0 +1,120 @@
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using Avalonia.Markup.Xaml.Templates;
|
||||
using Avalonia.Media;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using CrossLangDevStudio.Messages;
|
||||
using CrossLangDevStudio.Views;
|
||||
|
||||
namespace CrossLangDevStudio.ViewModels;
|
||||
|
||||
public partial class NewProjectDialogViewModel : ViewModelBase
|
||||
{
|
||||
public ObservableCollection<CrossLangTemplate> CrossLangTemplates { get; set; } = new ObservableCollection<CrossLangTemplate>();
|
||||
bool updated = false;
|
||||
string _name = "";
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
set
|
||||
{
|
||||
updated = true;
|
||||
SetProperty(ref _name, value, nameof(Name));
|
||||
}
|
||||
}
|
||||
|
||||
private void SelectProjectType(string name)
|
||||
{
|
||||
|
||||
|
||||
if (!updated)
|
||||
{
|
||||
var newName = name.Replace(" ", "");
|
||||
int i;
|
||||
for (i = 1; i < int.MaxValue; i++)
|
||||
{
|
||||
string name2 = $"{name}{i}";
|
||||
if (!Directory.Exists(Path.Combine(ParentDirectory, name2)))
|
||||
{
|
||||
Name = name2;
|
||||
updated = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[ObservableProperty]
|
||||
private string _parentDirectory = CrossLangShell.Settings.ProjectDirectory;
|
||||
CrossLangTemplate? _template = null;
|
||||
public CrossLangTemplate? SelectedTemplate
|
||||
{
|
||||
get
|
||||
{
|
||||
return _template;
|
||||
}
|
||||
set
|
||||
{
|
||||
SetProperty(ref _template, value, nameof(SelectedTemplate));
|
||||
if (value is not null)
|
||||
{
|
||||
SelectProjectType(value.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public NewProjectDialogViewModel()
|
||||
{
|
||||
foreach (var item in Directory.EnumerateFiles(Path.Combine(CrossLangShell.CrossLangConfigDirectory, "Templates"), "*.crvm"))
|
||||
{
|
||||
CrossLangFile file = new CrossLangFile();
|
||||
try
|
||||
{
|
||||
file.Load(item);
|
||||
CrossLangTemplates.Add(new CrossLangTemplate(Path.GetFileNameWithoutExtension(item), file));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void OK()
|
||||
{
|
||||
if (_template is not null && !string.IsNullOrWhiteSpace(Name) && !string.IsNullOrWhiteSpace(ParentDirectory))
|
||||
{
|
||||
var path = Path.Combine(ParentDirectory, Name);
|
||||
Directory.CreateDirectory(path);
|
||||
if (CrossLangShell.CreateProject(_template.TemplateName, path))
|
||||
{
|
||||
WeakReferenceMessenger.Default.Send(new NewProjectCloseMessage(path));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
[RelayCommand]
|
||||
private void Cancel()
|
||||
{
|
||||
WeakReferenceMessenger.Default.Send(new NewProjectCloseMessage(null));
|
||||
}
|
||||
}
|
||||
|
||||
public partial class CrossLangTemplate(string name,CrossLangFile file) : ObservableObject
|
||||
{
|
||||
|
||||
[ObservableProperty]
|
||||
private string _name = file.GetTemplatePrettyName();
|
||||
[ObservableProperty]
|
||||
private IImage _icon = file.GetIcon(64);
|
||||
|
||||
public string TemplateName = name;
|
||||
|
||||
}
|
||||
220
ViewModels/ProjectConfigurationViewModel.cs
Normal file
220
ViewModels/ProjectConfigurationViewModel.cs
Normal file
@@ -0,0 +1,220 @@
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Avalonia;
|
||||
using Avalonia.Platform.Storage;
|
||||
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using CrossLangDevStudio.Messages;
|
||||
using CrossLangDevStudio.Views;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace CrossLangDevStudio.ViewModels;
|
||||
|
||||
public partial class ProjectConfigurationViewModel : ViewModelBase, ISavable
|
||||
{
|
||||
/*
|
||||
<ComboBoxItem>Console Application</ComboBoxItem>
|
||||
<ComboBoxItem>Library</ComboBoxItem>
|
||||
<ComboBoxItem>Web Application</ComboBoxItem>
|
||||
<ComboBoxItem>Template</ComboBoxItem>
|
||||
<ComboBoxItem>Compile Tool</ComboBoxItem>
|
||||
<ComboBoxItem>Tool</ComboBoxItem>
|
||||
<ComboBoxItem>Archive</ComboBoxItem>
|
||||
*/
|
||||
static readonly string[] types = ["console","lib","app","template","compile_tool","tool","archive"];
|
||||
TabItemViewModel tab;
|
||||
public string FilePath { get; }
|
||||
bool _modified = false;
|
||||
private bool Modified
|
||||
{
|
||||
get => _modified;
|
||||
set
|
||||
{
|
||||
_modified = value;
|
||||
|
||||
if (value)
|
||||
{
|
||||
tab.Header = $"Project Configuration*";
|
||||
}
|
||||
else
|
||||
{
|
||||
tab.Header = "Project Configuration";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string _name;
|
||||
string _version;
|
||||
string _icon;
|
||||
string _maintainer;
|
||||
string _repository;
|
||||
string _homepage;
|
||||
|
||||
string _license;
|
||||
|
||||
string _templatename;
|
||||
string _templatenamepretty;
|
||||
|
||||
string _description;
|
||||
|
||||
int _type;
|
||||
|
||||
|
||||
public string Name
|
||||
{
|
||||
get => _name;
|
||||
set
|
||||
{
|
||||
Modified = true;
|
||||
SetProperty(ref _name, value, nameof(Name));
|
||||
}
|
||||
}
|
||||
public string Version
|
||||
{
|
||||
get => _version;
|
||||
set
|
||||
{
|
||||
Modified = true;
|
||||
SetProperty(ref _version, value, nameof(Version));
|
||||
}
|
||||
}
|
||||
|
||||
public string Icon
|
||||
{
|
||||
get => _icon;
|
||||
set
|
||||
{
|
||||
Modified = true;
|
||||
SetProperty(ref _icon, value, nameof(Icon));
|
||||
}
|
||||
}
|
||||
public string Maintainer
|
||||
{
|
||||
get => _maintainer;
|
||||
set
|
||||
{
|
||||
Modified = true;
|
||||
SetProperty(ref _maintainer, value, nameof(Maintainer));
|
||||
}
|
||||
}
|
||||
public string Homepage
|
||||
{
|
||||
get => _homepage;
|
||||
set
|
||||
{
|
||||
Modified = true;
|
||||
SetProperty(ref _homepage, value, nameof(Homepage));
|
||||
}
|
||||
}
|
||||
public string Repository
|
||||
{
|
||||
get => _repository;
|
||||
set
|
||||
{
|
||||
Modified = true;
|
||||
SetProperty(ref _repository, value, nameof(Repository));
|
||||
}
|
||||
}
|
||||
|
||||
public string License
|
||||
{
|
||||
get => _license;
|
||||
set
|
||||
{
|
||||
Modified = true;
|
||||
SetProperty(ref _license, value, nameof(License));
|
||||
}
|
||||
}
|
||||
|
||||
public string TemplateName
|
||||
{
|
||||
get => _templatename;
|
||||
set
|
||||
{
|
||||
Modified = true;
|
||||
SetProperty(ref _templatename, value, nameof(TemplateName));
|
||||
}
|
||||
}
|
||||
public string TemplateNamePretty
|
||||
{
|
||||
get => _templatenamepretty;
|
||||
set
|
||||
{
|
||||
Modified = true;
|
||||
SetProperty(ref _templatenamepretty, value, nameof(TemplateNamePretty));
|
||||
}
|
||||
}
|
||||
public string Description
|
||||
{
|
||||
get => _description;
|
||||
set
|
||||
{
|
||||
Modified = true;
|
||||
SetProperty(ref _description, value, nameof(Description));
|
||||
}
|
||||
}
|
||||
|
||||
public int Type
|
||||
{
|
||||
get => _type;
|
||||
set
|
||||
{
|
||||
Modified = true;
|
||||
SetProperty(ref _type, value, nameof(Type));
|
||||
}
|
||||
}
|
||||
|
||||
public ProjectConfigurationViewModel(string configPath, TabItemViewModel tab)
|
||||
{
|
||||
FilePath = configPath;
|
||||
this.tab = tab;
|
||||
|
||||
|
||||
var config = JsonConvert.DeserializeObject<CrossLangConfig>(File.ReadAllText(configPath));
|
||||
|
||||
_name = config?.Name ?? "";
|
||||
_version = config?.Version.ToString() ?? "1.0.0.0-dev";
|
||||
_icon = config?.Icon ?? "";
|
||||
_repository = config?.Info?.Repoository ?? "";
|
||||
_homepage = config?.Info?.HomePage ?? "";
|
||||
_maintainer = config?.Info?.Maintainer ?? "";
|
||||
_license = config?.Info?.License ?? "";
|
||||
_templatename = config?.Info?.TemplateName ?? "";
|
||||
_templatenamepretty = config?.Info?.TemplateNamePretty ?? "";
|
||||
_type = Array.IndexOf(types, config?.Info?.Type ?? "console");
|
||||
_type = _type == -1 ? 0 : _type;
|
||||
_description = config?.Info?.Description ?? "";
|
||||
|
||||
}
|
||||
[RelayCommand]
|
||||
|
||||
public void Save()
|
||||
{
|
||||
var config = JsonConvert.DeserializeObject<CrossLangConfig>(File.ReadAllText(FilePath)) ?? new CrossLangConfig();
|
||||
config.Name = Name;
|
||||
if (CrossLangVersion.TryParse(Version, out var vers))
|
||||
{
|
||||
config.Version = vers;
|
||||
}
|
||||
config.Icon = string.IsNullOrWhiteSpace(Icon) ? null : Icon;
|
||||
|
||||
config.Info.Description = string.IsNullOrWhiteSpace(Description) ? null : Description;
|
||||
config.Info.HomePage = string.IsNullOrWhiteSpace(Homepage) ? null : Homepage;
|
||||
config.Info.License = string.IsNullOrWhiteSpace(License) ? null : License;
|
||||
config.Info.Maintainer = string.IsNullOrWhiteSpace(Maintainer) ? null : Maintainer;
|
||||
config.Info.Repoository = string.IsNullOrWhiteSpace(Repository) ? null : Repository;
|
||||
config.Info.TemplateName = string.IsNullOrWhiteSpace(TemplateName) ? null : TemplateName;
|
||||
config.Info.TemplateNamePretty = string.IsNullOrWhiteSpace(TemplateNamePretty) ? null : TemplateNamePretty;
|
||||
config.Info.Type = types[Type];
|
||||
File.WriteAllText(FilePath, JsonConvert.SerializeObject(config, Formatting.Indented, new JsonSerializerSettings()
|
||||
{
|
||||
NullValueHandling = NullValueHandling.Ignore
|
||||
}));
|
||||
Modified = false;
|
||||
}
|
||||
}
|
||||
24
ViewModels/TabItemViewModel.cs
Normal file
24
ViewModels/TabItemViewModel.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
|
||||
namespace CrossLangDevStudio.ViewModels;
|
||||
|
||||
public partial class TabItemViewModel : ObservableObject
|
||||
{
|
||||
[ObservableProperty]
|
||||
private string _header = "";
|
||||
|
||||
public ViewModelBase? Body { get; set; }
|
||||
|
||||
|
||||
public override string ToString() => Header;
|
||||
|
||||
public void Save()
|
||||
{
|
||||
if (Body is ISavable savable)
|
||||
{
|
||||
savable.Save();
|
||||
}
|
||||
}
|
||||
}
|
||||
7
ViewModels/ViewModelBase.cs
Normal file
7
ViewModels/ViewModelBase.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
|
||||
namespace CrossLangDevStudio.ViewModels;
|
||||
|
||||
public class ViewModelBase : ObservableObject
|
||||
{
|
||||
}
|
||||
66
ViewModels/WelcomeViewModel.cs
Normal file
66
ViewModels/WelcomeViewModel.cs
Normal file
@@ -0,0 +1,66 @@
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Avalonia;
|
||||
using Avalonia.Platform.Storage;
|
||||
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using CrossLangDevStudio.Messages;
|
||||
using CrossLangDevStudio.Views;
|
||||
|
||||
namespace CrossLangDevStudio.ViewModels;
|
||||
|
||||
public partial class WelcomeViewModel : ViewModelBase
|
||||
{
|
||||
public MainWindowViewModel Main { get; }
|
||||
public WelcomeViewModel(MainWindowViewModel main)
|
||||
{
|
||||
Main = main;
|
||||
foreach (var proj in CrossLangShell.GetRecentProjects())
|
||||
{
|
||||
RecentProjects.Add(new RecentProject(proj,Main.LoadProject));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public ObservableCollection<RecentProject> RecentProjects { get; set; } = new ObservableCollection<RecentProject>();
|
||||
|
||||
[RelayCommand]
|
||||
private async Task NewProjectAsync()
|
||||
{
|
||||
await Main.NewProjectAsync();
|
||||
}
|
||||
[RelayCommand]
|
||||
private async Task OpenProjectAsync()
|
||||
{
|
||||
await Main.OpenProjectAsync();
|
||||
}
|
||||
}
|
||||
|
||||
public partial class RecentProject(string path, Action<string> onProjectClicked) : ObservableObject
|
||||
{
|
||||
public string ProjectPath { get; set; } = path;
|
||||
|
||||
private string GetDir()
|
||||
{
|
||||
var projPath = ProjectPath;
|
||||
var path = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
|
||||
if (projPath.StartsWith(path))
|
||||
{
|
||||
projPath= projPath.Replace(path, "~");
|
||||
}
|
||||
return projPath;
|
||||
}
|
||||
|
||||
|
||||
public string Name => $"{Path.GetFileName(ProjectPath)} ({GetDir()})";
|
||||
[RelayCommand]
|
||||
private void Click()
|
||||
{
|
||||
onProjectClicked(ProjectPath);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user