mirror of
https://onedev.site.tesses.net/crosslang/crosslangdevstudio
synced 2026-02-08 09:15:45 +00:00
Get way further
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -3,4 +3,5 @@ bin
|
|||||||
obj
|
obj
|
||||||
out
|
out
|
||||||
build
|
build
|
||||||
Installing
|
Installing
|
||||||
|
artifacts
|
||||||
@@ -17,13 +17,32 @@ jobs:
|
|||||||
commands: |
|
commands: |
|
||||||
apt update -y
|
apt update -y
|
||||||
apt install -y nsis cmake g++-mingw-w64-i686-win32 make
|
apt install -y nsis cmake g++-mingw-w64-i686-win32 make
|
||||||
|
mkdir artifacts
|
||||||
cd Packaging/Windows
|
cd Packaging/Windows
|
||||||
bash build.sh
|
bash build.sh
|
||||||
|
cd ../Linux
|
||||||
|
bash build.sh
|
||||||
|
bash publish.sh
|
||||||
|
envVars:
|
||||||
|
- name: GITEA_AUTH
|
||||||
|
value: '@secret:GITEA_AUTH@'
|
||||||
useTTY: true
|
useTTY: true
|
||||||
condition: ALL_PREVIOUS_STEPS_WERE_SUCCESSFUL
|
condition: ALL_PREVIOUS_STEPS_WERE_SUCCESSFUL
|
||||||
- !PublishArtifactStep
|
- !SCPCommandStep
|
||||||
name: Publish Windows Artifact
|
name: Copy Files
|
||||||
artifacts: Packaging/Windows/build/package/CrossLangDevStudio-Installer.exe
|
privateKeySecret: TRUENAS_SSH
|
||||||
|
source: artifacts
|
||||||
|
target: mike@@10.137.42.30:/mnt/storage24tb/Files/Public/CrossLangDevStudio/@build_number@
|
||||||
|
options: -r
|
||||||
|
condition: ALL_PREVIOUS_STEPS_WERE_SUCCESSFUL
|
||||||
|
- !SSHCommandStep
|
||||||
|
name: Link latest
|
||||||
|
remoteMachine: 10.137.42.30
|
||||||
|
userName: mike
|
||||||
|
privateKeySecret: TRUENAS_SSH
|
||||||
|
commands: |
|
||||||
|
cd /mnt/storage24tb/Files/Public/CrossLangDevStudio
|
||||||
|
ln -s @build_number@ latest
|
||||||
condition: ALL_PREVIOUS_STEPS_WERE_SUCCESSFUL
|
condition: ALL_PREVIOUS_STEPS_WERE_SUCCESSFUL
|
||||||
triggers:
|
triggers:
|
||||||
- !BranchUpdateTrigger
|
- !BranchUpdateTrigger
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
<!-- <fluent:FluentTheme /> -->
|
<!-- <fluent:FluentTheme /> -->
|
||||||
|
|
||||||
<themes:CustomTheme />
|
<themes:CustomTheme />
|
||||||
|
<StyleInclude Source="avares://AvaloniaEdit/Themes/Fluent/AvaloniaEdit.xaml" />
|
||||||
|
|
||||||
</Application.Styles>
|
</Application.Styles>
|
||||||
<Application.Resources>
|
<Application.Resources>
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Avalonia" Version="11.3.3" />
|
<PackageReference Include="Avalonia" Version="11.3.3" />
|
||||||
|
<PackageReference Include="Avalonia.AvaloniaEdit" Version="11.3.0" />
|
||||||
|
|
||||||
<PackageReference Include="Avalonia.Desktop" Version="11.3.3" />
|
<PackageReference Include="Avalonia.Desktop" Version="11.3.3" />
|
||||||
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.3.3" />
|
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.3.3" />
|
||||||
@@ -25,8 +26,11 @@
|
|||||||
<IncludeAssets Condition="'$(Configuration)' != 'Debug'">None</IncludeAssets>
|
<IncludeAssets Condition="'$(Configuration)' != 'Debug'">None</IncludeAssets>
|
||||||
<PrivateAssets Condition="'$(Configuration)' != 'Debug'">All</PrivateAssets>
|
<PrivateAssets Condition="'$(Configuration)' != 'Debug'">All</PrivateAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
<PackageReference Include="AvaloniaEdit.TextMate" Version="11.3.0" />
|
||||||
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.1" />
|
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.1" />
|
||||||
|
<PackageReference Include="MessageBox.Avalonia" Version="3.2.0" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
|
<PackageReference Include="SharpZipLib" Version="1.4.2" />
|
||||||
<PackageReference Include="SkiaSharp.NativeAssets.Linux.NoDependencies" Version="3.119.0" />
|
<PackageReference Include="SkiaSharp.NativeAssets.Linux.NoDependencies" Version="3.119.0" />
|
||||||
<PackageReference Include="Tabalonia" Version="0.10.7" />
|
<PackageReference Include="Tabalonia" Version="0.10.7" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
222
CrossLangFile.cs
222
CrossLangFile.cs
@@ -16,6 +16,24 @@ using Newtonsoft.Json.Linq;
|
|||||||
|
|
||||||
namespace CrossLangDevStudio;
|
namespace CrossLangDevStudio;
|
||||||
|
|
||||||
|
public static class CrossLangFileExtensions
|
||||||
|
{
|
||||||
|
public static void Skip(this Stream strm, long bytes)
|
||||||
|
{
|
||||||
|
byte[] data = new byte[1024];
|
||||||
|
if (strm.CanSeek)
|
||||||
|
strm.Position += bytes;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int read = strm.Read(data, 0, (int)Math.Min(bytes, data.LongLength));
|
||||||
|
if (read == 0) return;
|
||||||
|
bytes -= read;
|
||||||
|
} while (bytes != 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class CrossLangFile
|
public class CrossLangFile
|
||||||
{
|
{
|
||||||
@@ -68,7 +86,7 @@ public class CrossLangFile
|
|||||||
return Strings[(int)index];
|
return Strings[(int)index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
uint count = ReadInt();
|
uint count = ReadInt();
|
||||||
for (uint i = 0; i < count; i++)
|
for (uint i = 0; i < count; i++)
|
||||||
@@ -77,6 +95,42 @@ public class CrossLangFile
|
|||||||
uint sectionSize = ReadInt();
|
uint sectionSize = ReadInt();
|
||||||
switch (section)
|
switch (section)
|
||||||
{
|
{
|
||||||
|
case "FUNS":
|
||||||
|
{
|
||||||
|
uint chks = ReadInt();
|
||||||
|
for (uint j = 0; j < chks; j++)
|
||||||
|
{
|
||||||
|
uint fnParts = ReadInt();
|
||||||
|
|
||||||
|
string[] parts = new string[fnParts];
|
||||||
|
for (uint k = 0; k < fnParts; k++)
|
||||||
|
{
|
||||||
|
parts[k] = GetString();
|
||||||
|
}
|
||||||
|
uint fid = ReadInt();
|
||||||
|
Functions.Add(new CrossLangFunction(parts, fid));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "CHKS":
|
||||||
|
{
|
||||||
|
uint chks = ReadInt();
|
||||||
|
for (uint j = 0; j < chks; j++)
|
||||||
|
{
|
||||||
|
uint fnParts = ReadInt();
|
||||||
|
|
||||||
|
string[] parts = new string[fnParts];
|
||||||
|
for (uint k = 0; k < fnParts; k++)
|
||||||
|
{
|
||||||
|
parts[k] = GetString();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint len = ReadInt();
|
||||||
|
strm.Skip(len);
|
||||||
|
Chunks.Add(parts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
case "STRS":
|
case "STRS":
|
||||||
{
|
{
|
||||||
uint theCount = ReadInt();
|
uint theCount = ReadInt();
|
||||||
@@ -109,8 +163,69 @@ public class CrossLangFile
|
|||||||
Dependencies.Add(new CrossLangDependency() { Name = name, Version = version });
|
Dependencies.Add(new CrossLangDependency() { Name = name, Version = version });
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case "CLSS":
|
||||||
|
{
|
||||||
|
uint chks = ReadInt();
|
||||||
|
for (uint j = 0; j < chks; j++)
|
||||||
|
{
|
||||||
|
string docs = GetString();
|
||||||
|
uint namePartLen = ReadInt();
|
||||||
|
string[] nameParts = new string[namePartLen];
|
||||||
|
for (uint k = 0; k < namePartLen; k++)
|
||||||
|
{
|
||||||
|
nameParts[k] = GetString();
|
||||||
|
}
|
||||||
|
string name = string.Join(".", nameParts);
|
||||||
|
uint inhPartLen = ReadInt();
|
||||||
|
string[] inhParts = new string[inhPartLen];
|
||||||
|
for (uint k = 0; k < inhPartLen; k++)
|
||||||
|
{
|
||||||
|
inhParts[k] = GetString();
|
||||||
|
}
|
||||||
|
string inh = string.Join(".", inhParts);
|
||||||
|
uint entCount = ReadInt();
|
||||||
|
CrossLangClassEntry[] entries = new CrossLangClassEntry[entCount];
|
||||||
|
for (uint k = 0; k < entCount; k++)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Ensure(stream,main_header,1);
|
||||||
|
uint8_t sig = main_header[0];
|
||||||
|
ent.isAbstract = (sig & 0b00001000) != 0;
|
||||||
|
ent.isFunction = (sig & 0b00000100) == 0;
|
||||||
|
ent.modifier = (TClassModifier)(sig & 3);
|
||||||
|
ent.documentation = GetString(stream);
|
||||||
|
ent.name = GetString(stream);
|
||||||
|
uint32_t arglen = EnsureInt(stream);
|
||||||
|
for(uint32_t l = 0; l < arglen; l++)
|
||||||
|
ent.args.push_back(GetString(stream));
|
||||||
|
ent.chunkId = EnsureInt(stream);
|
||||||
|
cls.entry.push_back(ent);
|
||||||
|
*/
|
||||||
|
int sig = strm.ReadByte();
|
||||||
|
|
||||||
|
if (sig == -1) throw new EndOfStreamException("Could not read flags byte");
|
||||||
|
|
||||||
|
bool isAbstract = ((byte)sig & 0b00001000) != 0;
|
||||||
|
bool isFunction = ((byte)sig & 0b00000100) == 0;
|
||||||
|
CrossLangClassEntryModifier modifier = (CrossLangClassEntryModifier)(sig & 3);
|
||||||
|
string ent_doc = GetString();
|
||||||
|
string ent_name = GetString();
|
||||||
|
uint arglen = ReadInt();
|
||||||
|
string[] ent_args = new string[arglen];
|
||||||
|
for (uint l = 0; l < arglen; l++)
|
||||||
|
{
|
||||||
|
ent_args[l] = GetString();
|
||||||
|
}
|
||||||
|
uint chunkId = ReadInt();
|
||||||
|
|
||||||
|
entries[k] = new CrossLangClassEntry(isAbstract, isFunction, modifier, ent_doc, ent_name, ent_args, chunkId);
|
||||||
|
}
|
||||||
|
Classes.Add(new CrossLangClass(docs, nameParts, name, inhParts, inh, entries));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
strm.Position += sectionSize;
|
strm.Skip(sectionSize);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -125,7 +240,7 @@ public class CrossLangFile
|
|||||||
|
|
||||||
public CrossLangInfo InfoObject => JsonConvert.DeserializeObject<CrossLangInfo>(Info) ?? new CrossLangInfo();
|
public CrossLangInfo InfoObject => JsonConvert.DeserializeObject<CrossLangInfo>(Info) ?? new CrossLangInfo();
|
||||||
|
|
||||||
public Bitmap GetIcon(int height=128)
|
public Bitmap GetIcon(int height = 128)
|
||||||
{
|
{
|
||||||
using (Stream strm = (Icon > -1 && Icon < Resources.Count) ? new MemoryStream(Resources[Icon], false) : AssetLoader.Open(new Uri("avares://CrossLangDevStudio/Assets/crosslang.png")))
|
using (Stream strm = (Icon > -1 && Icon < Resources.Count) ? new MemoryStream(Resources[Icon], false) : AssetLoader.Open(new Uri("avares://CrossLangDevStudio/Assets/crosslang.png")))
|
||||||
{
|
{
|
||||||
@@ -133,25 +248,85 @@ public class CrossLangFile
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal string GetTemplatePrettyName()
|
internal string GetPrettyName()
|
||||||
{
|
{
|
||||||
var info = InfoObject;
|
var info = InfoObject;
|
||||||
if (info is not null)
|
if (info is not null)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrWhiteSpace(info.TemplateNamePretty)) return info.TemplateNamePretty;
|
if (!string.IsNullOrWhiteSpace(info.ShortNamePretty)) return info.ShortNamePretty;
|
||||||
if (!string.IsNullOrWhiteSpace(info.TemplateName)) return info.TemplateName;
|
if (!string.IsNullOrWhiteSpace(info.ShortName)) return info.ShortName;
|
||||||
}
|
}
|
||||||
return this.Name;
|
return this.Name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<string> Strings { get; } = new List<string>();
|
public List<string> Strings { get; } = new List<string>();
|
||||||
|
|
||||||
public List<byte[]> Resources { get; } = new List<byte[]>();
|
public List<byte[]> Resources { get; } = new List<byte[]>();
|
||||||
|
|
||||||
public List<CrossLangDependency> Dependencies { get; } = new List<CrossLangDependency>();
|
public List<CrossLangDependency> Dependencies { get; } = new List<CrossLangDependency>();
|
||||||
|
|
||||||
|
public List<CrossLangFunction> Functions { get; } = new List<CrossLangFunction>();
|
||||||
|
public List<CrossLangClass> Classes { get; } = new List<CrossLangClass>();
|
||||||
|
public List<string[]> Chunks { get; } = new List<string[]>();
|
||||||
|
|
||||||
|
}
|
||||||
|
public class CrossLangClass(string doc, string[] nameParts, string name, string[] inhParts, string inh, CrossLangClassEntry[] ents)
|
||||||
|
{
|
||||||
|
public string Documentation => doc;
|
||||||
|
|
||||||
|
public string[] NameParts => nameParts;
|
||||||
|
public string Name => name;
|
||||||
|
|
||||||
|
public string[] InheritParts => inhParts;
|
||||||
|
|
||||||
|
public string Inherit => inh;
|
||||||
|
|
||||||
|
public CrossLangClassEntry[] Entries => ents;
|
||||||
|
}
|
||||||
|
public enum CrossLangClassEntryModifier
|
||||||
|
{
|
||||||
|
Private,
|
||||||
|
Protected,
|
||||||
|
Public,
|
||||||
|
Static
|
||||||
|
}
|
||||||
|
public class CrossLangClassEntry(bool isAbstract, bool isFunction, CrossLangClassEntryModifier modifier, string documentation, string name, string[] args, uint chunkId)
|
||||||
|
{
|
||||||
|
public bool IsAbstract => isAbstract;
|
||||||
|
|
||||||
|
public bool IsFunction => isFunction;
|
||||||
|
|
||||||
|
public CrossLangClassEntryModifier Modifier => modifier;
|
||||||
|
|
||||||
|
public string Documentation => documentation;
|
||||||
|
public string Name => name;
|
||||||
|
|
||||||
|
public string[] Arguments => args;
|
||||||
|
|
||||||
|
public uint ChunkId => chunkId;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Ensure(stream,main_header,1);
|
||||||
|
uint8_t sig = main_header[0];
|
||||||
|
ent.isAbstract = (sig & 0b00001000) != 0;
|
||||||
|
ent.isFunction = (sig & 0b00000100) == 0;
|
||||||
|
ent.modifier = (TClassModifier)(sig & 3);
|
||||||
|
ent.documentation = GetString(stream);
|
||||||
|
ent.name = GetString(stream);
|
||||||
|
uint32_t arglen = EnsureInt(stream);
|
||||||
|
for(uint32_t l = 0; l < arglen; l++)
|
||||||
|
ent.args.push_back(GetString(stream));
|
||||||
|
ent.chunkId = EnsureInt(stream);
|
||||||
|
cls.entry.push_back(ent);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class CrossLangFunction(string[] nameParts, uint chunkId)
|
||||||
|
{
|
||||||
|
public string[] NameParts => nameParts;
|
||||||
|
public uint ChunkId => chunkId;
|
||||||
|
}
|
||||||
|
|
||||||
public class CrossLangConfig
|
public class CrossLangConfig
|
||||||
{
|
{
|
||||||
@@ -190,10 +365,13 @@ public class CrossLangInfo
|
|||||||
[JsonProperty("description")]
|
[JsonProperty("description")]
|
||||||
public string? Description { get; set; } //optional but tells people about the package
|
public string? Description { get; set; } //optional but tells people about the package
|
||||||
|
|
||||||
[JsonProperty("template_name")]
|
[JsonProperty("short_name")]
|
||||||
public string? TemplateName { get; set; }
|
public string? ShortName { get; set; }
|
||||||
[JsonProperty("template_name_pretty")]
|
|
||||||
public string? TemplateNamePretty { get; set; }
|
public string? ToolName { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("short_name_pretty")]
|
||||||
|
public string? ShortNamePretty { get; set; }
|
||||||
|
|
||||||
[JsonProperty("template_project_dependencies")]
|
[JsonProperty("template_project_dependencies")]
|
||||||
public JToken? TemplateDependencies { get; set; }
|
public JToken? TemplateDependencies { get; set; }
|
||||||
@@ -201,9 +379,9 @@ public class CrossLangInfo
|
|||||||
[JsonProperty("template_info")]
|
[JsonProperty("template_info")]
|
||||||
public JToken? TemplateInfo { get; set; }
|
public JToken? TemplateInfo { get; set; }
|
||||||
[JsonProperty("template_extra_text_ftles")]
|
[JsonProperty("template_extra_text_ftles")]
|
||||||
public JToken? TemplateExtraTextFiles { get; set; }
|
public JToken? TemplateExtraTextFiles { get; set; }
|
||||||
[JsonProperty("template_ignored_files")]
|
[JsonProperty("template_ignored_files")]
|
||||||
public JToken? TemplateIgnoredFiles { get; set; }
|
public JToken? TemplateIgnoredFiles { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class CrossLangDependency
|
public class CrossLangDependency
|
||||||
@@ -229,9 +407,9 @@ public class CrossLangVersionConverter : Newtonsoft.Json.JsonConverter<CrossLang
|
|||||||
string? s = reader.Value as string;
|
string? s = reader.Value as string;
|
||||||
if (!string.IsNullOrWhiteSpace(s))
|
if (!string.IsNullOrWhiteSpace(s))
|
||||||
{
|
{
|
||||||
|
|
||||||
if (CrossLangVersion.TryParse(s, out var version)) return version;
|
if (CrossLangVersion.TryParse(s, out var version)) return version;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasExistingValue)
|
if (hasExistingValue)
|
||||||
@@ -244,7 +422,7 @@ public class CrossLangVersionConverter : Newtonsoft.Json.JsonConverter<CrossLang
|
|||||||
writer.WriteValue(value.ToString());
|
writer.WriteValue(value.ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
[Newtonsoft.Json.JsonConverter( typeof(CrossLangVersionConverter))]
|
[Newtonsoft.Json.JsonConverter(typeof(CrossLangVersionConverter))]
|
||||||
public struct CrossLangVersion : IComparable<CrossLangVersion>, IComparable
|
public struct CrossLangVersion : IComparable<CrossLangVersion>, IComparable
|
||||||
{
|
{
|
||||||
public void CopyTo(byte[] data, int offset = 0)
|
public void CopyTo(byte[] data, int offset = 0)
|
||||||
@@ -350,10 +528,10 @@ public struct CrossLangVersion : IComparable<CrossLangVersion>, IComparable
|
|||||||
{
|
{
|
||||||
if (offset + 5 > data.Length) return;
|
if (offset + 5 > data.Length) return;
|
||||||
|
|
||||||
Major = data[offset+0];
|
Major = data[offset + 0];
|
||||||
Minor = data[offset+1];
|
Minor = data[offset + 1];
|
||||||
Patch = data[offset+2];
|
Patch = data[offset + 2];
|
||||||
ushort build = (ushort)(data[offset+3] << 8 | data[offset+4]);
|
ushort build = (ushort)(data[offset + 3] << 8 | data[offset + 4]);
|
||||||
Build = (ushort)(build >> 2);
|
Build = (ushort)(build >> 2);
|
||||||
Stage = (CrossLangVersionStage)(build & 3);
|
Stage = (CrossLangVersionStage)(build & 3);
|
||||||
}
|
}
|
||||||
@@ -363,7 +541,7 @@ public struct CrossLangVersion : IComparable<CrossLangVersion>, IComparable
|
|||||||
|
|
||||||
public ushort Build { get; set; } = 0;
|
public ushort Build { get; set; } = 0;
|
||||||
|
|
||||||
public static CrossLangVersion OnePointZeroProd => new CrossLangVersion(){Major=1,Minor=0,Patch=0,Build=0,Stage= CrossLangVersionStage.Production};
|
public static CrossLangVersion OnePointZeroProd => new CrossLangVersion() { Major = 1, Minor = 0, Patch = 0, Build = 0, Stage = CrossLangVersionStage.Production };
|
||||||
|
|
||||||
public CrossLangVersionStage Stage { get; set; } = CrossLangVersionStage.Development;
|
public CrossLangVersionStage Stage { get; set; } = CrossLangVersionStage.Development;
|
||||||
|
|
||||||
@@ -386,7 +564,7 @@ public struct CrossLangVersion : IComparable<CrossLangVersion>, IComparable
|
|||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
string stage="dev";
|
string stage = "dev";
|
||||||
switch (Stage)
|
switch (Stage)
|
||||||
{
|
{
|
||||||
case CrossLangVersionStage.Development:
|
case CrossLangVersionStage.Development:
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ class CrossLangShell
|
|||||||
return ["https://cpkg.tesseslanguage.com/"];
|
return ["https://cpkg.tesseslanguage.com/"];
|
||||||
}
|
}
|
||||||
public static string[] ProjectTypes { get; } = ["console", "lib", "webapp", "template", "compile_tool", "tool", "archive"];
|
public static string[] ProjectTypes { get; } = ["console", "lib", "webapp", "template", "compile_tool", "tool", "archive"];
|
||||||
public static string[] ProjectProperTypes { get; } = ["Console Application","Library","Web Application","Template","Compile Tool","Tool","Archive"];
|
public static string[] ProjectProperTypes { get; } = ["Console Application", "Library", "Web Application", "Template", "Compile Tool", "Tool", "Archive"];
|
||||||
private static void EscapeBashElement(StringBuilder builder, string val)
|
private static void EscapeBashElement(StringBuilder builder, string val)
|
||||||
{
|
{
|
||||||
builder.Append("\"");
|
builder.Append("\"");
|
||||||
@@ -53,27 +53,27 @@ class CrossLangShell
|
|||||||
private static string EscapeBashCommand(string name, string[] args)
|
private static string EscapeBashCommand(string name, string[] args)
|
||||||
{
|
{
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
EscapeBashElement(builder,name);
|
EscapeBashElement(builder, name);
|
||||||
foreach (var item in args)
|
foreach (var item in args)
|
||||||
{
|
{
|
||||||
builder.Append(' ');
|
builder.Append(' ');
|
||||||
EscapeBashElement(builder,item);
|
EscapeBashElement(builder, item);
|
||||||
}
|
}
|
||||||
builder.Append(" ; read -p \"Press Enter to close.\"");
|
builder.Append(" ; read -p \"Press Enter to close.\"");
|
||||||
return builder.ToString();
|
return builder.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string EscapeMacBashCommand(string workDir, bool keepOpen,string name, string[] args)
|
private static string EscapeMacBashCommand(string workDir, bool keepOpen, string name, string[] args)
|
||||||
{
|
{
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
builder.Append("cd ");
|
builder.Append("cd ");
|
||||||
EscapeBashElement(builder, workDir);
|
EscapeBashElement(builder, workDir);
|
||||||
builder.Append(" ; ");
|
builder.Append(" ; ");
|
||||||
EscapeBashElement(builder,name);
|
EscapeBashElement(builder, name);
|
||||||
foreach (var item in args)
|
foreach (var item in args)
|
||||||
{
|
{
|
||||||
builder.Append(' ');
|
builder.Append(' ');
|
||||||
EscapeBashElement(builder,item);
|
EscapeBashElement(builder, item);
|
||||||
}
|
}
|
||||||
if (keepOpen)
|
if (keepOpen)
|
||||||
builder.Append(" ; read -p \"Press Enter to close.\"");
|
builder.Append(" ; read -p \"Press Enter to close.\"");
|
||||||
@@ -96,7 +96,7 @@ class CrossLangShell
|
|||||||
settings = JsonConvert.DeserializeObject<CrossLangSettings>(File.ReadAllText(settingsFile));
|
settings = JsonConvert.DeserializeObject<CrossLangSettings>(File.ReadAllText(settingsFile));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return settings is null ? settings = new CrossLangSettings() : settings;
|
return settings is null ? settings = new CrossLangSettings() : settings;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -158,18 +158,18 @@ class CrossLangShell
|
|||||||
if (execDir is not null)
|
if (execDir is not null)
|
||||||
{
|
{
|
||||||
var dir = Path.GetDirectoryName(execDir);
|
var dir = Path.GetDirectoryName(execDir);
|
||||||
if(dir is not null)
|
if (dir is not null)
|
||||||
paths.Add(dir);
|
paths.Add(dir);
|
||||||
}
|
}
|
||||||
foreach (var item in paths)
|
foreach (var item in paths)
|
||||||
|
{
|
||||||
|
var path = Path.Combine(item, exec);
|
||||||
|
if (File.Exists(path)) return path;
|
||||||
|
foreach (var ext in (Environment.GetEnvironmentVariable("PATHEXT") ?? "").Split(Path.PathSeparator))
|
||||||
{
|
{
|
||||||
var path = Path.Combine(item, exec);
|
if (File.Exists(path + ext)) return path + ext;
|
||||||
if (File.Exists(path)) return path;
|
|
||||||
foreach (var ext in (Environment.GetEnvironmentVariable("PATHEXT") ?? "").Split(Path.PathSeparator))
|
|
||||||
{
|
|
||||||
if (File.Exists(path + ext)) return path + ext;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,6 +188,10 @@ class CrossLangShell
|
|||||||
return !string.IsNullOrWhiteSpace(CrossLangPath);
|
return !string.IsNullOrWhiteSpace(CrossLangPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public static void PushProjectInFolder(string folder)
|
||||||
|
{
|
||||||
|
OpenTerminal(false, folder, CrossLangPath, "upload-package");
|
||||||
|
}
|
||||||
public static void BuildProjectInFolder(string folder)
|
public static void BuildProjectInFolder(string folder)
|
||||||
{
|
{
|
||||||
OpenTerminal(false, folder, CrossLangPath, "build");
|
OpenTerminal(false, folder, CrossLangPath, "build");
|
||||||
@@ -252,7 +256,7 @@ class CrossLangShell
|
|||||||
}
|
}
|
||||||
process.Start();
|
process.Start();
|
||||||
}
|
}
|
||||||
if (File.Exists(xfce_terminal))
|
else if (File.Exists(xfce_terminal))
|
||||||
{
|
{
|
||||||
using Process process = new Process();
|
using Process process = new Process();
|
||||||
process.StartInfo.WorkingDirectory = workingDirectory;
|
process.StartInfo.WorkingDirectory = workingDirectory;
|
||||||
@@ -435,11 +439,40 @@ class CrossLangShell
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static async Task RunCommandAsync(string workingDirectory, string commandName, params string[] args)
|
||||||
|
{
|
||||||
|
using Process process = new();
|
||||||
|
process.StartInfo.WorkingDirectory = workingDirectory;
|
||||||
|
process.StartInfo.FileName = GetRealPath(commandName);
|
||||||
|
process.StartInfo.CreateNoWindow = true;
|
||||||
|
process.StartInfo.UseShellExecute = false;
|
||||||
|
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
|
||||||
|
foreach (var arg in args)
|
||||||
|
process.StartInfo.ArgumentList.Add(arg);
|
||||||
|
|
||||||
|
if (process.Start()) await process.WaitForExitAsync();
|
||||||
|
}
|
||||||
|
|
||||||
private static string GetCrossLangDirectory()
|
private static string GetCrossLangDirectory()
|
||||||
{
|
{
|
||||||
|
|
||||||
string path = CrossLangPath;
|
string path = CrossLangPath;
|
||||||
if (string.IsNullOrWhiteSpace(path)) return "";
|
if (string.IsNullOrWhiteSpace(path)) return "";
|
||||||
|
using Process process0 = new Process();
|
||||||
|
process0.StartInfo.ArgumentList.Add("configdir");
|
||||||
|
process0.StartInfo.FileName = path;
|
||||||
|
process0.StartInfo.CreateNoWindow = true;
|
||||||
|
process0.StartInfo.RedirectStandardOutput = true;
|
||||||
|
process0.StartInfo.UseShellExecute = false;
|
||||||
|
process0.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
|
||||||
|
process0.StartInfo.RedirectStandardInput = true;
|
||||||
|
if (process0.Start())
|
||||||
|
{
|
||||||
|
process0.StandardInput.WriteLine("y");
|
||||||
|
process0.WaitForExit();
|
||||||
|
var text = process0.StandardOutput.ReadToEnd();
|
||||||
|
return (text ?? "").Replace("\n", "").Replace("\r", "");
|
||||||
|
}
|
||||||
using Process process = new Process();
|
using Process process = new Process();
|
||||||
process.StartInfo.ArgumentList.Add("configdir");
|
process.StartInfo.ArgumentList.Add("configdir");
|
||||||
process.StartInfo.FileName = path;
|
process.StartInfo.FileName = path;
|
||||||
@@ -457,6 +490,29 @@ class CrossLangShell
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<string> GetReferenceAsync()
|
||||||
|
{
|
||||||
|
await RunCommandAsync(Environment.CurrentDirectory, "crosslang", "docs", "--reference");
|
||||||
|
string path = CrossLangPath;
|
||||||
|
if (string.IsNullOrWhiteSpace(path)) return "";
|
||||||
|
using Process process = new Process();
|
||||||
|
process.StartInfo.ArgumentList.Add("docs");
|
||||||
|
process.StartInfo.ArgumentList.Add("--reference-path");
|
||||||
|
process.StartInfo.FileName = path;
|
||||||
|
process.StartInfo.CreateNoWindow = true;
|
||||||
|
process.StartInfo.RedirectStandardOutput = true;
|
||||||
|
process.StartInfo.UseShellExecute = false;
|
||||||
|
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
|
||||||
|
if (process.Start())
|
||||||
|
{
|
||||||
|
|
||||||
|
process.WaitForExit();
|
||||||
|
var text = process.StandardOutput.ReadToEnd();
|
||||||
|
return (text ?? "").Replace("\n", "").Replace("\r", "");
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
internal static bool CreateProject(string templateName, string path)
|
internal static bool CreateProject(string templateName, string path)
|
||||||
{
|
{
|
||||||
string cpath = CrossLangPath;
|
string cpath = CrossLangPath;
|
||||||
@@ -478,6 +534,18 @@ class CrossLangShell
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static async Task PublishAsync(string project, string identifier, string prefix, string outputDir)
|
||||||
|
{
|
||||||
|
List<string> args = new List<string>();
|
||||||
|
args.Add("publish");
|
||||||
|
args.Add($"--runtime-package-prefix={prefix}");
|
||||||
|
if (!string.IsNullOrWhiteSpace(outputDir))
|
||||||
|
args.Add($"--out={outputDir}");
|
||||||
|
args.Add(identifier);
|
||||||
|
|
||||||
|
await RunCommandAsync(project,"crosslang",args.ToArray());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class CrossLangSettings
|
public class CrossLangSettings
|
||||||
|
|||||||
4
Messages/PublishCloseMessage.cs
Normal file
4
Messages/PublishCloseMessage.cs
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
using CommunityToolkit.Mvvm.Messaging.Messages;
|
||||||
|
namespace CrossLangDevStudio.Messages;
|
||||||
|
public class PublishCloseMessage : AsyncRequestMessage<bool>;
|
||||||
7
Messages/PublishMessage.cs
Normal file
7
Messages/PublishMessage.cs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
using CommunityToolkit.Mvvm.Messaging.Messages;
|
||||||
|
namespace CrossLangDevStudio.Messages;
|
||||||
|
public class PublishMessage(string path) : AsyncRequestMessage<Task>
|
||||||
|
{
|
||||||
|
public string Path => path;
|
||||||
|
}
|
||||||
72
Models/ConsolePackageManger.cs
Normal file
72
Models/ConsolePackageManger.cs
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Avalonia.Controls;
|
||||||
|
|
||||||
|
namespace CrossLangDevStudio.Models;
|
||||||
|
|
||||||
|
public class ConsolePackageManager : IPackageManager
|
||||||
|
{
|
||||||
|
public string Filter => "console";
|
||||||
|
|
||||||
|
private IEnumerable<string> GetFiles()
|
||||||
|
{
|
||||||
|
var path = Path.Combine(CrossLangShell.CrossLangConfigDirectory, "ConsoleApps");
|
||||||
|
if (Directory.Exists(path))
|
||||||
|
foreach (var dir in Directory.EnumerateDirectories(path))
|
||||||
|
{
|
||||||
|
var file = Path.Combine(dir, $"{Path.GetFileName(dir)}.crvm");
|
||||||
|
if (File.Exists(file)) yield return file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<CrossLangDependency> GetInstalledPackages()
|
||||||
|
{
|
||||||
|
foreach (var item in GetFiles())
|
||||||
|
{
|
||||||
|
var file = new CrossLangFile();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
file.Load(item);
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
yield return new CrossLangDependency { Name = file.Name, Version = file.Version };
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task InstallPackageAsync(string name, CrossLangVersion version)
|
||||||
|
{
|
||||||
|
await CrossLangShell.RunCommandAsync(Environment.CurrentDirectory, "crosslang", ["install-console", name, $"--version={version.ToString()}"]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UninstallPackage(string name)
|
||||||
|
{
|
||||||
|
foreach (var item in GetFiles())
|
||||||
|
{
|
||||||
|
var file = new CrossLangFile();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
file.Load(item);
|
||||||
|
if (name == file.Name)
|
||||||
|
{
|
||||||
|
var dir = Path.GetDirectoryName(item);
|
||||||
|
if(dir is not null)
|
||||||
|
Directory.Delete(dir,true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
70
Models/TemplatePackageManager.cs
Normal file
70
Models/TemplatePackageManager.cs
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Avalonia.Controls;
|
||||||
|
|
||||||
|
namespace CrossLangDevStudio.Models;
|
||||||
|
|
||||||
|
public class TemplatePackageManager : IPackageManager
|
||||||
|
{
|
||||||
|
public string Filter => "template";
|
||||||
|
|
||||||
|
private IEnumerable<string> GetFiles()
|
||||||
|
{
|
||||||
|
var path = Path.Combine(CrossLangShell.CrossLangConfigDirectory, "Templates");
|
||||||
|
if (Directory.Exists(path))
|
||||||
|
foreach (var dir in Directory.EnumerateDirectories(path))
|
||||||
|
{
|
||||||
|
var file = Path.Combine(dir, $"{Path.GetFileName(dir)}.crvm");
|
||||||
|
if (File.Exists(file)) yield return file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<CrossLangDependency> GetInstalledPackages()
|
||||||
|
{
|
||||||
|
foreach (var item in GetFiles())
|
||||||
|
{
|
||||||
|
var file = new CrossLangFile();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
file.Load(item);
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
yield return new CrossLangDependency { Name = file.Name, Version = file.Version };
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task InstallPackageAsync(string name, CrossLangVersion version)
|
||||||
|
{
|
||||||
|
await CrossLangShell.RunCommandAsync(Environment.CurrentDirectory, "crosslang", ["install-template", name, $"--version={version.ToString()}"]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UninstallPackage(string name)
|
||||||
|
{
|
||||||
|
foreach (var item in GetFiles())
|
||||||
|
{
|
||||||
|
var file = new CrossLangFile();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
file.Load(item);
|
||||||
|
if (name == file.Name)
|
||||||
|
{
|
||||||
|
File.Delete(item);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
72
Models/ToolPackageManager.cs
Normal file
72
Models/ToolPackageManager.cs
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Avalonia.Controls;
|
||||||
|
|
||||||
|
namespace CrossLangDevStudio.Models;
|
||||||
|
|
||||||
|
public class ToolPackageManager : IPackageManager
|
||||||
|
{
|
||||||
|
public string Filter => "tool";
|
||||||
|
|
||||||
|
private IEnumerable<string> GetFiles()
|
||||||
|
{
|
||||||
|
var path = Path.Combine(CrossLangShell.CrossLangConfigDirectory, "Tools");
|
||||||
|
if (Directory.Exists(path))
|
||||||
|
foreach (var dir in Directory.EnumerateDirectories(path))
|
||||||
|
{
|
||||||
|
var file = Path.Combine(dir, $"{Path.GetFileName(dir)}.crvm");
|
||||||
|
if (File.Exists(file)) yield return file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<CrossLangDependency> GetInstalledPackages()
|
||||||
|
{
|
||||||
|
foreach (var item in GetFiles())
|
||||||
|
{
|
||||||
|
var file = new CrossLangFile();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
file.Load(item);
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
yield return new CrossLangDependency { Name = file.Name, Version = file.Version };
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task InstallPackageAsync(string name, CrossLangVersion version)
|
||||||
|
{
|
||||||
|
await CrossLangShell.RunCommandAsync(Environment.CurrentDirectory, "crosslang", ["install-tool", name, $"--version={version.ToString()}"]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UninstallPackage(string name)
|
||||||
|
{
|
||||||
|
foreach (var item in GetFiles())
|
||||||
|
{
|
||||||
|
var file = new CrossLangFile();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
file.Load(item);
|
||||||
|
if (name == file.Name)
|
||||||
|
{
|
||||||
|
var dir = Path.GetDirectoryName(item);
|
||||||
|
if(dir is not null)
|
||||||
|
Directory.Delete(dir,true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
72
Models/WebAppPackageManager.cs
Normal file
72
Models/WebAppPackageManager.cs
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Avalonia.Controls;
|
||||||
|
|
||||||
|
namespace CrossLangDevStudio.Models;
|
||||||
|
|
||||||
|
public class WebAppPackageManager : IPackageManager
|
||||||
|
{
|
||||||
|
public string Filter => "webapp";
|
||||||
|
|
||||||
|
private IEnumerable<string> GetFiles()
|
||||||
|
{
|
||||||
|
var path = Path.Combine(CrossLangShell.CrossLangConfigDirectory, "WebApps");
|
||||||
|
if (Directory.Exists(path))
|
||||||
|
foreach (var dir in Directory.EnumerateDirectories(path))
|
||||||
|
{
|
||||||
|
var file = Path.Combine(dir, $"{Path.GetFileName(dir)}.crvm");
|
||||||
|
if (File.Exists(file)) yield return file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<CrossLangDependency> GetInstalledPackages()
|
||||||
|
{
|
||||||
|
foreach (var item in GetFiles())
|
||||||
|
{
|
||||||
|
var file = new CrossLangFile();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
file.Load(item);
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
yield return new CrossLangDependency { Name = file.Name, Version = file.Version };
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task InstallPackageAsync(string name, CrossLangVersion version)
|
||||||
|
{
|
||||||
|
await CrossLangShell.RunCommandAsync(Environment.CurrentDirectory, "crosslang", ["install-webapp", name, $"--version={version.ToString()}"]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UninstallPackage(string name)
|
||||||
|
{
|
||||||
|
foreach (var item in GetFiles())
|
||||||
|
{
|
||||||
|
var file = new CrossLangFile();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
file.Load(item);
|
||||||
|
if (name == file.Name)
|
||||||
|
{
|
||||||
|
var dir = Path.GetDirectoryName(item);
|
||||||
|
if(dir is not null)
|
||||||
|
Directory.Delete(dir,true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,5 +11,23 @@ cp ../../debian/control-amd64 DEBIAN/control
|
|||||||
cp ../../crosslang-devstudio.desktop usr/share/applications/
|
cp ../../crosslang-devstudio.desktop usr/share/applications/
|
||||||
cp ../../crossdev usr/bin/crossdev
|
cp ../../crossdev usr/bin/crossdev
|
||||||
chmod 755 usr/bin/crossdev
|
chmod 755 usr/bin/crossdev
|
||||||
cd ..
|
cd opt
|
||||||
|
tar cvzf ../../../../../artifacts/crosslang-devstudio-x86_64.tar.gz .
|
||||||
|
cd ../..
|
||||||
dpkg-deb --build crosslang-devstudio_1.0.0_amd64/
|
dpkg-deb --build crosslang-devstudio_1.0.0_amd64/
|
||||||
|
|
||||||
|
|
||||||
|
mkdir crosslang-devstudio_1.0.0_arm64
|
||||||
|
cd crosslang-devstudio_1.0.0_arm64
|
||||||
|
dotnet publish -c Release -r linux-arm64 -o opt/CrossLangDevStudio -p:PublishReadyToRun=true -p:PublishSingleFile=true --self-contained ../../../../CrossLangDevStudio.csproj
|
||||||
|
mkdir DEBIAN
|
||||||
|
mkdir -p usr/share/applications
|
||||||
|
mkdir -p usr/bin
|
||||||
|
cp ../../debian/control-arm64 DEBIAN/control
|
||||||
|
cp ../../crosslang-devstudio.desktop usr/share/applications/
|
||||||
|
cp ../../crossdev usr/bin/crossdev
|
||||||
|
chmod 755 usr/bin/crossdev
|
||||||
|
cd opt
|
||||||
|
tar cvzf ../../../../../artifacts/crosslang-devstudio-aarch64.tar.gz .
|
||||||
|
cd ../..
|
||||||
|
dpkg-deb --build crosslang-devstudio_1.0.0_arm64/
|
||||||
8
Packaging/Linux/debian/control-arm64
Normal file
8
Packaging/Linux/debian/control-arm64
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
Package: crosslang-devstudio
|
||||||
|
Version: 1.0.0
|
||||||
|
Architecture: arm64
|
||||||
|
Essential: no
|
||||||
|
Priority: optional
|
||||||
|
Depends: crosslang
|
||||||
|
Maintainer: Mike Nolan
|
||||||
|
Description: IDE for CrossLang
|
||||||
@@ -4,3 +4,21 @@ curl --user tesses50:$GITEA_AUTH -X DELETE \
|
|||||||
curl --user tesses50:$GITEA_AUTH \
|
curl --user tesses50:$GITEA_AUTH \
|
||||||
--upload-file build/crosslang-devstudio_1.0.0_amd64.deb \
|
--upload-file build/crosslang-devstudio_1.0.0_amd64.deb \
|
||||||
https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/jammy/main/upload
|
https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/jammy/main/upload
|
||||||
|
|
||||||
|
curl --user tesses50:$GITEA_AUTH -X DELETE \
|
||||||
|
https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/jammy/main/crosslang-devstudio/1.0.0/arm64
|
||||||
|
curl --user tesses50:$GITEA_AUTH \
|
||||||
|
--upload-file build/crosslang-devstudio_1.0.0_arm64.deb \
|
||||||
|
https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/jammy/main/upload
|
||||||
|
|
||||||
|
curl --user tesses50:$GITEA_AUTH -X DELETE \
|
||||||
|
https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/plucky/main/crosslang-devstudio/1.0.0/amd64
|
||||||
|
curl --user tesses50:$GITEA_AUTH \
|
||||||
|
--upload-file build/crosslang-devstudio_1.0.0_amd64.deb \
|
||||||
|
https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/plucky/main/upload
|
||||||
|
|
||||||
|
curl --user tesses50:$GITEA_AUTH -X DELETE \
|
||||||
|
https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/plucky/main/crosslang-devstudio/1.0.0/arm64
|
||||||
|
curl --user tesses50:$GITEA_AUTH \
|
||||||
|
--upload-file build/crosslang-devstudio_1.0.0_arm64.deb \
|
||||||
|
https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/plucky/main/upload
|
||||||
|
|||||||
@@ -17,4 +17,6 @@ cd package
|
|||||||
dotnet publish -c Release -r win-x86 -o bin -p:PublishReadyToRun=true -p:PublishSingleFile=true --self-contained ../../../../CrossLangDevStudio.csproj
|
dotnet publish -c Release -r win-x86 -o bin -p:PublishReadyToRun=true -p:PublishSingleFile=true --self-contained ../../../../CrossLangDevStudio.csproj
|
||||||
cp ../../script.nsh .
|
cp ../../script.nsh .
|
||||||
cp ../../license.txt .
|
cp ../../license.txt .
|
||||||
makensis script.nsh
|
makensis script.nsh
|
||||||
|
mv crosslang-devstudio-win32.exe ../../../../artifacts/
|
||||||
|
zip -r ../../../../artifacts/crosslang-devstudio-win32.zip bin share
|
||||||
@@ -29,7 +29,7 @@ LicenseData "license.txt"
|
|||||||
# This will be in the installer/uninstaller's title bar
|
# This will be in the installer/uninstaller's title bar
|
||||||
Name "${COMPANYNAME} - ${APPNAME}"
|
Name "${COMPANYNAME} - ${APPNAME}"
|
||||||
Icon "crosslang.ico"
|
Icon "crosslang.ico"
|
||||||
outFile "CrossLangDevStudio-Installer.exe"
|
outFile "crosslang-devstudio-win32.exe"
|
||||||
|
|
||||||
!include LogicLib.nsh
|
!include LogicLib.nsh
|
||||||
|
|
||||||
|
|||||||
92
ViewModels/AddProjectReferenceViewModel.cs
Normal file
92
ViewModels/AddProjectReferenceViewModel.cs
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Avalonia;
|
||||||
|
using Avalonia.Media;
|
||||||
|
using Avalonia.Platform.Storage;
|
||||||
|
|
||||||
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
using CommunityToolkit.Mvvm.Input;
|
||||||
|
using CommunityToolkit.Mvvm.Messaging;
|
||||||
|
using CrossLangDevStudio.Messages;
|
||||||
|
using CrossLangDevStudio.Views;
|
||||||
|
using MsBox.Avalonia;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace CrossLangDevStudio.ViewModels;
|
||||||
|
|
||||||
|
|
||||||
|
public partial class AddProjectReferenceViewModel : ViewModelBase
|
||||||
|
{
|
||||||
|
public AddProjectReferenceViewModel(string projectDir)
|
||||||
|
{
|
||||||
|
ProjectDirectory = projectDir;
|
||||||
|
var data = File.ReadAllText(Path.Combine(projectDir, "cross.json"));
|
||||||
|
var jsonData = JsonConvert.DeserializeObject<CrossLangConfig>(data) ?? new CrossLangConfig();
|
||||||
|
foreach (var item in jsonData.ProjectDependencies)
|
||||||
|
References.Add(new ProjectReferenceEntry(this, item));
|
||||||
|
}
|
||||||
|
public string ProjectDirectory { get; init; }
|
||||||
|
public ObservableCollection<ProjectReferenceEntry> References { get; } = new ObservableCollection<ProjectReferenceEntry>();
|
||||||
|
|
||||||
|
public void Remove(ProjectReferenceEntry projectReferenceEntry)
|
||||||
|
{
|
||||||
|
References.Remove(projectReferenceEntry);
|
||||||
|
var data = File.ReadAllText(Path.Combine(ProjectDirectory, "cross.json"));
|
||||||
|
var jsonData = JsonConvert.DeserializeObject<CrossLangConfig>(data) ?? new CrossLangConfig();
|
||||||
|
jsonData.ProjectDependencies.Remove(projectReferenceEntry.Path);
|
||||||
|
File.WriteAllText(Path.Combine(ProjectDirectory, "cross.json"), JsonConvert.SerializeObject(jsonData, Formatting.Indented, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore }));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
private async Task AddProjectAsync()
|
||||||
|
{
|
||||||
|
var window = await WeakReferenceMessenger.Default.Send<GetWindowMessage>();
|
||||||
|
var dir = await window.StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions() { Title = "Add Project Dependency" });
|
||||||
|
if (dir.Count != 0)
|
||||||
|
{
|
||||||
|
string? path = dir[0].TryGetLocalPath();
|
||||||
|
if (!string.IsNullOrWhiteSpace(path))
|
||||||
|
{
|
||||||
|
var jsonFile = Path.Combine(path, "cross.json");
|
||||||
|
if (!File.Exists(jsonFile))
|
||||||
|
{
|
||||||
|
await MessageBoxManager.GetMessageBoxStandard("Error", $"Could not find cross.json in folder {path}", MsBox.Avalonia.Enums.ButtonEnum.Ok, MsBox.Avalonia.Enums.Icon.Error).ShowAsync();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
string projectPath = Path.GetRelativePath(this.ProjectDirectory, path);
|
||||||
|
var abs = Path.GetFullPath(projectPath, ProjectDirectory);
|
||||||
|
|
||||||
|
foreach (var item in References)
|
||||||
|
{
|
||||||
|
if (Path.GetFullPath(item.Path, ProjectDirectory) == abs)
|
||||||
|
{
|
||||||
|
await MessageBoxManager.GetMessageBoxStandard("Error", $"Project {path} already exists in your project.", MsBox.Avalonia.Enums.ButtonEnum.Ok, MsBox.Avalonia.Enums.Icon.Error).ShowAsync();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var data = File.ReadAllText(Path.Combine(ProjectDirectory, "cross.json"));
|
||||||
|
var jsonData = JsonConvert.DeserializeObject<CrossLangConfig>(data) ?? new CrossLangConfig();
|
||||||
|
jsonData.ProjectDependencies.Add(projectPath);
|
||||||
|
File.WriteAllText(Path.Combine(ProjectDirectory, "cross.json"), JsonConvert.SerializeObject(jsonData, Formatting.Indented, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore }));
|
||||||
|
References.Add(new ProjectReferenceEntry(this, projectPath));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class ProjectReferenceEntry(AddProjectReferenceViewModel parent,string path) : ObservableObject
|
||||||
|
{
|
||||||
|
public string Path => path;
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
private void Remove()
|
||||||
|
{
|
||||||
|
parent.Remove(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
103
ViewModels/CRVMViewerViewModel.cs
Normal file
103
ViewModels/CRVMViewerViewModel.cs
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Avalonia;
|
||||||
|
using Avalonia.Media;
|
||||||
|
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 class CRVMViewerViewModel : ViewModelBase
|
||||||
|
{
|
||||||
|
public string FilePath { get; set; }
|
||||||
|
public CRVMViewerViewModel(string path)
|
||||||
|
{
|
||||||
|
FilePath = path;
|
||||||
|
var clf = new CrossLangFile();
|
||||||
|
using (var strm = File.OpenRead(path))
|
||||||
|
{
|
||||||
|
|
||||||
|
clf.Load(strm);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
foreach (var fn in clf.Functions)
|
||||||
|
{
|
||||||
|
string docs = $"/^{fn.NameParts[0]}^/";
|
||||||
|
string name = string.Join(".", fn.NameParts.Skip(1));
|
||||||
|
string args = string.Join(", ", clf.Chunks[(int)fn.ChunkId]);
|
||||||
|
Functions.Add(new Function(docs, name, args));
|
||||||
|
}
|
||||||
|
foreach (var cls in clf.Classes)
|
||||||
|
{
|
||||||
|
string docs = $"/^{cls.Documentation}^/";
|
||||||
|
ObservableCollection<Class.ClassEntry> entries = new ObservableCollection<Class.ClassEntry>();
|
||||||
|
|
||||||
|
foreach (var item in cls.Entries)
|
||||||
|
{
|
||||||
|
string modifiers = $"\t{item.Modifier.ToString().ToLower()} ";
|
||||||
|
if (item.IsFunction && item.IsAbstract)
|
||||||
|
modifiers += "abstract ";
|
||||||
|
|
||||||
|
Class.ClassEntry ce = new Class.ClassEntry($"\t/^{item.Documentation}^/", item.Name, modifiers, item.IsFunction, item.IsFunction ? string.Join(", ", item.Arguments) : "");
|
||||||
|
entries.Add(ce);
|
||||||
|
}
|
||||||
|
|
||||||
|
Classes.Add(new Class(docs, cls.Name, cls.Inherit, entries));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObservableCollection<Function> Functions { get; set; } = new ObservableCollection<Function>();
|
||||||
|
|
||||||
|
public ObservableCollection<Class> Classes { get; set; } = new ObservableCollection<Class>();
|
||||||
|
|
||||||
|
public class Function(string docs, string name, string args) : ObservableObject
|
||||||
|
{
|
||||||
|
public string Name => name;
|
||||||
|
|
||||||
|
public string Documentation => docs;
|
||||||
|
|
||||||
|
public string Args => args;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Class(string docs, string name, string inherits, ObservableCollection<Class.ClassEntry> entries) : ObservableObject
|
||||||
|
{
|
||||||
|
public string Documentation => docs;
|
||||||
|
|
||||||
|
public string Name => name;
|
||||||
|
|
||||||
|
public string Inherits => inherits == "ClassObject" ? "" : inherits;
|
||||||
|
|
||||||
|
public string InheritsColon => inherits == "ClassObject" ? "" : " : ";
|
||||||
|
|
||||||
|
public ObservableCollection<ClassEntry> Entries => entries;
|
||||||
|
|
||||||
|
public class ClassEntry(string docs,string name, string modifiers, bool isFunction, string args)
|
||||||
|
{
|
||||||
|
public string Documentation => docs;
|
||||||
|
|
||||||
|
public string Name => name;
|
||||||
|
public string Modifiers => modifiers;
|
||||||
|
|
||||||
|
public IBrush NameColor => new SolidColorBrush(isFunction ? 0xFFDCDCAA : 0xFF9CDCFE);
|
||||||
|
|
||||||
|
public IBrush LeftParenColor => new SolidColorBrush(isFunction ? 0xFFC586C0 : 0xFFCCCCCC);
|
||||||
|
|
||||||
|
public string LeftParen => isFunction ? "(" : ";";
|
||||||
|
|
||||||
|
public string RightParen => isFunction ? ")" : "";
|
||||||
|
|
||||||
|
|
||||||
|
public string Args => args;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,13 +5,22 @@ using System.Threading.Tasks;
|
|||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Platform.Storage;
|
using Avalonia.Platform.Storage;
|
||||||
|
using AvaloniaEdit;
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
using CommunityToolkit.Mvvm.Input;
|
using CommunityToolkit.Mvvm.Input;
|
||||||
using CommunityToolkit.Mvvm.Messaging;
|
using CommunityToolkit.Mvvm.Messaging;
|
||||||
using CrossLangDevStudio.Messages;
|
using CrossLangDevStudio.Messages;
|
||||||
using CrossLangDevStudio.Views;
|
using CrossLangDevStudio.Views;
|
||||||
|
using AvaloniaEdit.CodeCompletion;
|
||||||
|
using AvaloniaEdit.Document;
|
||||||
|
using AvaloniaEdit.Editing;
|
||||||
|
using AvaloniaEdit.Folding;
|
||||||
|
using AvaloniaEdit.Rendering;
|
||||||
|
using TextMateSharp.Grammars;
|
||||||
|
using AvaloniaEdit.TextMate;
|
||||||
|
using Avalonia.Input;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Avalonia.Media;
|
||||||
namespace CrossLangDevStudio.ViewModels;
|
namespace CrossLangDevStudio.ViewModels;
|
||||||
|
|
||||||
public partial class FileEditorViewModel : ViewModelBase, ISavable
|
public partial class FileEditorViewModel : ViewModelBase, ISavable
|
||||||
@@ -19,7 +28,7 @@ public partial class FileEditorViewModel : ViewModelBase, ISavable
|
|||||||
TabItemViewModel tab;
|
TabItemViewModel tab;
|
||||||
public string FilePath { get; }
|
public string FilePath { get; }
|
||||||
bool _modified = false;
|
bool _modified = false;
|
||||||
private bool Modified
|
public bool Modified
|
||||||
{
|
{
|
||||||
get => _modified;
|
get => _modified;
|
||||||
set
|
set
|
||||||
@@ -36,30 +45,72 @@ public partial class FileEditorViewModel : ViewModelBase, ISavable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private string _text = "";
|
|
||||||
|
|
||||||
public string Text
|
|
||||||
{
|
|
||||||
get => _text;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
|
|
||||||
Modified = true;
|
|
||||||
this.SetProperty(ref _text, value, nameof(Text));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public FileEditorViewModel(string path,TabItemViewModel tab)
|
TextEditor textEdit = new TextEditor();
|
||||||
|
|
||||||
|
public TextEditor TextEditor => textEdit;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public FileEditorViewModel(string path, TabItemViewModel tab)
|
||||||
{
|
{
|
||||||
this.tab = tab;
|
this.tab = tab;
|
||||||
FilePath = path;
|
FilePath = path;
|
||||||
_text = File.ReadAllText(path);
|
textEdit.ShowLineNumbers = true;
|
||||||
|
textEdit.FontSize = 24;
|
||||||
|
string ext = Path.GetExtension(FilePath);
|
||||||
|
if (ext == ".tcross")
|
||||||
|
{
|
||||||
|
ext = ".go";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
|
||||||
|
var _registryOptions = new RegistryOptions(ThemeName.Dark);
|
||||||
|
|
||||||
|
var _textMateInstallation = textEdit.InstallTextMate(_registryOptions);
|
||||||
|
|
||||||
|
//definition.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//Here we are getting the language by the extension and right after that we are initializing grammar with this language.
|
||||||
|
//And that's all 😀, you are ready to use AvaloniaEdit with syntax highlighting!
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//AssetLoader.Open(new Uri("avares://CrossLangDevStudio/Assets/crosslang.png")
|
||||||
|
|
||||||
|
_textMateInstallation.SetGrammar(_registryOptions.GetScopeByLanguageId(_registryOptions.GetLanguageByExtension(ext).Id));
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
textEdit.Text = File.ReadAllText(path);
|
||||||
|
textEdit.TextChanged += (sender, e) =>
|
||||||
|
{
|
||||||
|
Modified = true;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void Save()
|
public void Save()
|
||||||
{
|
{
|
||||||
File.WriteAllText(FilePath, Text);
|
|
||||||
|
File.WriteAllText(FilePath, textEdit.Text);
|
||||||
Modified = false;
|
Modified = false;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public void SaveRecovery(string path)
|
||||||
|
{
|
||||||
|
|
||||||
|
File.WriteAllText(path, textEdit.Text);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,10 @@
|
|||||||
namespace CrossLangDevStudio.ViewModels;
|
namespace CrossLangDevStudio.ViewModels;
|
||||||
|
|
||||||
interface ISavable
|
interface ISavable
|
||||||
{
|
{
|
||||||
|
string FilePath { get; }
|
||||||
|
bool Modified { get; set; }
|
||||||
void Save();
|
void Save();
|
||||||
|
|
||||||
|
void SaveRecovery(string path);
|
||||||
}
|
}
|
||||||
@@ -2,15 +2,21 @@
|
|||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Platform.Storage;
|
using Avalonia.Platform.Storage;
|
||||||
|
using Avalonia.Threading;
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
using CommunityToolkit.Mvvm.Input;
|
using CommunityToolkit.Mvvm.Input;
|
||||||
using CommunityToolkit.Mvvm.Messaging;
|
using CommunityToolkit.Mvvm.Messaging;
|
||||||
using CrossLangDevStudio.Messages;
|
using CrossLangDevStudio.Messages;
|
||||||
using CrossLangDevStudio.Models;
|
using CrossLangDevStudio.Models;
|
||||||
using CrossLangDevStudio.Views;
|
using CrossLangDevStudio.Views;
|
||||||
|
using MsBox.Avalonia;
|
||||||
|
using MsBox.Avalonia.Enums;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Tabalonia.Events;
|
||||||
|
|
||||||
namespace CrossLangDevStudio.ViewModels;
|
namespace CrossLangDevStudio.ViewModels;
|
||||||
|
|
||||||
@@ -26,6 +32,7 @@ public partial class MainWindowViewModel : ViewModelBase
|
|||||||
public ObservableCollection<ProjectFileNode> ProjectFiles { get; } = new ObservableCollection<ProjectFileNode>();
|
public ObservableCollection<ProjectFileNode> ProjectFiles { get; } = new ObservableCollection<ProjectFileNode>();
|
||||||
|
|
||||||
public EventHandler<Tabalonia.Events.CloseLastTabEventArgs>? Closed { get; } = null;
|
public EventHandler<Tabalonia.Events.CloseLastTabEventArgs>? Closed { get; } = null;
|
||||||
|
public EventHandler<Tabalonia.Events.TabClosingEventArgs>? ClosingTab { get; }
|
||||||
|
|
||||||
public TabItemViewModel WelcomePage
|
public TabItemViewModel WelcomePage
|
||||||
{
|
{
|
||||||
@@ -49,16 +56,120 @@ public partial class MainWindowViewModel : ViewModelBase
|
|||||||
value?.Click?.Invoke();
|
value?.Click?.Invoke();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
private Avalonia.Threading.DispatcherTimer timer=new ();
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
private void Welcome()
|
||||||
|
{
|
||||||
|
foreach (var item in TabItems)
|
||||||
|
{
|
||||||
|
if (item.Body is WelcomeViewModel)
|
||||||
|
{
|
||||||
|
SelectedTab = item;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AddTab(WelcomePage);
|
||||||
|
}
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
private async Task WebsiteAsync()
|
||||||
|
{
|
||||||
|
var win = await WeakReferenceMessenger.Default.Send<GetWindowMessage>(new GetWindowMessage());
|
||||||
|
if (win is not null)
|
||||||
|
{
|
||||||
|
await win.Launcher.LaunchUriAsync(new Uri("https://crosslang.tesseslanguage.com/"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
private async Task VideoDocumentationAsync()
|
||||||
|
{
|
||||||
|
var win = await WeakReferenceMessenger.Default.Send<GetWindowMessage>(new GetWindowMessage());
|
||||||
|
if (win is not null)
|
||||||
|
{
|
||||||
|
await win.Launcher.LaunchUriAsync(new Uri("https://peertube.site.tesses.net/c/crosslang"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[RelayCommand]
|
||||||
|
private async Task DocumentationAsync()
|
||||||
|
{
|
||||||
|
var win = await WeakReferenceMessenger.Default.Send<GetWindowMessage>(new GetWindowMessage());
|
||||||
|
if (win is not null)
|
||||||
|
{
|
||||||
|
await win.Launcher.LaunchUriAsync(new Uri("https://crosslang.tesseslanguage.com/language-features/index.html"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task CloseTabAsync(TabClosingEventArgs e, ISavable savable)
|
||||||
|
{
|
||||||
|
var box = MessageBoxManager
|
||||||
|
.GetMessageBoxStandard("Save?", $"Do you want to save {Path.GetFileName(savable.FilePath)}.?",
|
||||||
|
ButtonEnum.YesNoCancel, Icon.Question);
|
||||||
|
var msg = await WeakReferenceMessenger.Default.Send<GetWindowMessage>();
|
||||||
|
if (msg is not null)
|
||||||
|
{
|
||||||
|
switch (await box.ShowWindowDialogAsync(msg))
|
||||||
|
{
|
||||||
|
case ButtonResult.Yes:
|
||||||
|
savable.Save();
|
||||||
|
break;
|
||||||
|
case ButtonResult.Cancel:
|
||||||
|
e.Cancel = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool HasUnsaved
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
foreach (var item in TabItems)
|
||||||
|
{
|
||||||
|
if (item.Body is ISavable s && s.Modified) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public MainWindowViewModel(string[] args)
|
public MainWindowViewModel(string[] args)
|
||||||
{
|
{
|
||||||
|
this.ClosingTab = (sender, e) =>
|
||||||
|
{
|
||||||
|
|
||||||
|
if (e.Item is TabItemViewModel vm)
|
||||||
|
{
|
||||||
|
if (vm.Body is ISavable savable)
|
||||||
|
{
|
||||||
|
if (savable.Modified)
|
||||||
|
{
|
||||||
|
//thanks https://github.com/AvaloniaUI/Avalonia/issues/4810#issuecomment-704372304
|
||||||
|
using (var source = new CancellationTokenSource())
|
||||||
|
{
|
||||||
|
CloseTabAsync(e, savable).ContinueWith(e => source.Cancel(), TaskScheduler.FromCurrentSynchronizationContext());
|
||||||
|
Dispatcher.UIThread.MainLoop(source.Token);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
timer.Interval = TimeSpan.FromMinutes(1);
|
||||||
|
timer.Tick += (sender, e) =>
|
||||||
|
{
|
||||||
|
SaveRecovery();
|
||||||
|
};
|
||||||
|
|
||||||
if (args.Length == 1)
|
if (args.Length == 1)
|
||||||
{
|
{
|
||||||
LoadProject(args[0]);
|
LoadProject(args[0]);
|
||||||
}
|
}
|
||||||
if (string.IsNullOrWhiteSpace(CurrentProject))
|
if (string.IsNullOrWhiteSpace(CurrentProject))
|
||||||
this.TabItems.Add(WelcomePage);
|
this.TabItems.Add(WelcomePage);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -74,7 +185,7 @@ public partial class MainWindowViewModel : ViewModelBase
|
|||||||
var newTabItem = new NewTabViewModel(this, tab);
|
var newTabItem = new NewTabViewModel(this, tab);
|
||||||
tab.Body = newTabItem;
|
tab.Body = newTabItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return tab;
|
return tab;
|
||||||
@@ -82,12 +193,19 @@ public partial class MainWindowViewModel : ViewModelBase
|
|||||||
|
|
||||||
internal void LoadProject(string obj)
|
internal void LoadProject(string obj)
|
||||||
{
|
{
|
||||||
|
timer.Stop(); //we don't want autorecovery timer ticking when we change projects
|
||||||
if (!File.Exists(Path.Combine(obj, "cross.json")))
|
if (!File.Exists(Path.Combine(obj, "cross.json")))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
CrossLangShell.EnsureRecent(obj);
|
CrossLangShell.EnsureRecent(obj);
|
||||||
CurrentProject = obj.TrimEnd(Path.DirectorySeparatorChar);
|
CurrentProject = obj.TrimEnd(Path.DirectorySeparatorChar);
|
||||||
|
//we don't care that it isn't awaited due to only Refreshing here (you can referesh in GUI)
|
||||||
|
//and the timer starting after async call inside the async function
|
||||||
|
//so I think I know what I am doing
|
||||||
|
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
|
||||||
|
InitRecoveryAsync();
|
||||||
|
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
|
||||||
Refresh(CurrentProject);
|
Refresh(CurrentProject);
|
||||||
}
|
}
|
||||||
[RelayCommand]
|
[RelayCommand]
|
||||||
@@ -102,7 +220,7 @@ public partial class MainWindowViewModel : ViewModelBase
|
|||||||
|
|
||||||
private void Refresh(string obj)
|
private void Refresh(string obj)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
for (int i = 0; i < TabItems.Count; i++)
|
for (int i = 0; i < TabItems.Count; i++)
|
||||||
@@ -122,11 +240,11 @@ public partial class MainWindowViewModel : ViewModelBase
|
|||||||
|
|
||||||
OpenProjectConfig();
|
OpenProjectConfig();
|
||||||
}),
|
}),
|
||||||
new ProjectFileNode("Packages", ()=>{
|
new ProjectFileNode("Project Packages", ()=>{
|
||||||
OpenProjectPackages();
|
OpenProjectPackages();
|
||||||
}),
|
}),
|
||||||
new ProjectFileNode("Project Dependencies",()=>{
|
new ProjectFileNode("Project Dependencies (folders)",()=>{
|
||||||
|
OpenProjectDependencies();
|
||||||
})
|
})
|
||||||
])
|
])
|
||||||
|
|
||||||
@@ -155,7 +273,227 @@ public partial class MainWindowViewModel : ViewModelBase
|
|||||||
ProjectFiles.Clear();
|
ProjectFiles.Clear();
|
||||||
ProjectFiles.Add(new ProjectFileNode(Path.GetFileName(obj), entries));
|
ProjectFiles.Add(new ProjectFileNode(Path.GetFileName(obj), entries));
|
||||||
}
|
}
|
||||||
|
private int proj_id = -1;
|
||||||
|
private async Task InitRecoveryAsync()
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
var dir = Path.Combine(CrossLangShell.CrossLangConfigDirectory, "DevStudio", "Recovery");
|
||||||
|
foreach (var item in Directory.EnumerateDirectories(dir))
|
||||||
|
{
|
||||||
|
if (int.TryParse(Path.GetFileName(item), out int id))
|
||||||
|
{
|
||||||
|
if (id >= i) i = id + 1;
|
||||||
|
|
||||||
|
var file = $"{item}.json";
|
||||||
|
if (File.Exists(file))
|
||||||
|
{
|
||||||
|
var cfg = JsonConvert.DeserializeObject<RecoveryConfig>(File.ReadAllText(file));
|
||||||
|
if (cfg is not null)
|
||||||
|
{
|
||||||
|
if (cfg.ProjectDirectory == CurrentProject)
|
||||||
|
{
|
||||||
|
proj_id = id;
|
||||||
|
|
||||||
|
if (cfg.HasRecovery)
|
||||||
|
{
|
||||||
|
var box = MessageBoxManager
|
||||||
|
.GetMessageBoxStandard("Autorecovery", $"Found a autorecovery from {cfg.Date} do you want to load it?",
|
||||||
|
ButtonEnum.YesNo, Icon.Question);
|
||||||
|
var msg = await WeakReferenceMessenger.Default.Send<GetWindowMessage>();
|
||||||
|
if (msg is not null && await box.ShowWindowDialogAsync(msg) == ButtonResult.Yes)
|
||||||
|
{
|
||||||
|
CopyDir(item, CurrentProject);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
cfg.HasRecovery = false;
|
||||||
|
File.WriteAllText(file, JsonConvert.SerializeObject(cfg));
|
||||||
|
}
|
||||||
|
|
||||||
|
//WeakReferenceMessenger.Default.Send
|
||||||
|
|
||||||
|
timer.Start();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
proj_id = i;
|
||||||
|
|
||||||
|
|
||||||
|
timer.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CopyDir(string src, string dest)
|
||||||
|
{
|
||||||
|
foreach (var dir in Directory.EnumerateDirectories(src))
|
||||||
|
{
|
||||||
|
var destDir = Path.Combine(dest, Path.GetFileName(dir));
|
||||||
|
Directory.CreateDirectory(destDir);
|
||||||
|
CopyDir(dir, destDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var file in Directory.EnumerateFiles(src))
|
||||||
|
{
|
||||||
|
var destFile = Path.Combine(dest, Path.GetFileName(file));
|
||||||
|
|
||||||
|
File.Copy(file, destFile, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SaveRecovery()
|
||||||
|
{
|
||||||
|
if (proj_id == -1 || !Directory.Exists(CurrentProject)) return;
|
||||||
|
var id = proj_id;
|
||||||
|
var dir = Path.Combine(CrossLangShell.CrossLangConfigDirectory, "DevStudio", "Recovery", $"{id}_tmp");
|
||||||
|
var dirdest = Path.Combine(CrossLangShell.CrossLangConfigDirectory, "DevStudio", "Recovery", $"{id}");
|
||||||
|
Directory.CreateDirectory(dir);
|
||||||
|
bool hasAnything = false;
|
||||||
|
|
||||||
|
foreach (var item in TabItems)
|
||||||
|
{
|
||||||
|
if (item.Body is ISavable savable && savable.Modified)
|
||||||
|
{
|
||||||
|
if (savable.FilePath.StartsWith(CurrentProject))
|
||||||
|
{
|
||||||
|
var path = Path.GetRelativePath(CurrentProject, savable.FilePath);
|
||||||
|
string? dirPath = Path.GetDirectoryName(path);
|
||||||
|
if (dirPath is not null)
|
||||||
|
Directory.CreateDirectory(Path.Combine(dir, dirPath));
|
||||||
|
|
||||||
|
savable.SaveRecovery(Path.Combine(dir, path));
|
||||||
|
hasAnything = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Directory.Exists(dirdest))
|
||||||
|
{
|
||||||
|
Directory.Delete(dirdest, true);
|
||||||
|
}
|
||||||
|
if (hasAnything)
|
||||||
|
{
|
||||||
|
Directory.Move(dir, dirdest);
|
||||||
|
File.WriteAllText($"{dirdest}.json", JsonConvert.SerializeObject(new RecoveryConfig { Date = DateTime.Now, ProjectDirectory = CurrentProject, HasRecovery=true }));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Directory.Delete(dir, true);
|
||||||
|
|
||||||
|
File.WriteAllText($"{dirdest}.json", JsonConvert.SerializeObject(new RecoveryConfig { Date = DateTime.Now, ProjectDirectory = CurrentProject, HasRecovery=false }));
|
||||||
|
}
|
||||||
|
Directory.CreateDirectory(dirdest);
|
||||||
|
}
|
||||||
|
[RelayCommand]
|
||||||
|
private void InstallTool()
|
||||||
|
{
|
||||||
|
foreach (var item in TabItems)
|
||||||
|
{
|
||||||
|
if (item.Body is PackageManagerViewModel vm)
|
||||||
|
{
|
||||||
|
if (vm.Packages is ToolPackageManager)
|
||||||
|
{
|
||||||
|
SelectedTab = item;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AddTab(new TabItemViewModel()
|
||||||
|
{
|
||||||
|
Header = "Tool Packages",
|
||||||
|
Body = new PackageManagerViewModel(this, new ToolPackageManager())
|
||||||
|
});
|
||||||
|
}
|
||||||
|
[RelayCommand]
|
||||||
|
private void InstallTemplate()
|
||||||
|
{
|
||||||
|
foreach (var item in TabItems)
|
||||||
|
{
|
||||||
|
if (item.Body is PackageManagerViewModel vm)
|
||||||
|
{
|
||||||
|
if (vm.Packages is TemplatePackageManager)
|
||||||
|
{
|
||||||
|
SelectedTab = item;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AddTab(new TabItemViewModel()
|
||||||
|
{
|
||||||
|
Header = "Template Packages",
|
||||||
|
Body = new PackageManagerViewModel(this, new TemplatePackageManager())
|
||||||
|
});
|
||||||
|
}
|
||||||
|
[RelayCommand]
|
||||||
|
private void InstallConsole()
|
||||||
|
{
|
||||||
|
foreach (var item in TabItems)
|
||||||
|
{
|
||||||
|
if (item.Body is PackageManagerViewModel vm)
|
||||||
|
{
|
||||||
|
if (vm.Packages is ConsolePackageManager)
|
||||||
|
{
|
||||||
|
SelectedTab = item;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AddTab(new TabItemViewModel()
|
||||||
|
{
|
||||||
|
Header = "Console Packages",
|
||||||
|
Body = new PackageManagerViewModel(this, new ConsolePackageManager())
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
private void InstallWebApp()
|
||||||
|
{
|
||||||
|
foreach (var item in TabItems)
|
||||||
|
{
|
||||||
|
if (item.Body is PackageManagerViewModel vm)
|
||||||
|
{
|
||||||
|
if (vm.Packages is WebAppPackageManager)
|
||||||
|
{
|
||||||
|
SelectedTab = item;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AddTab(new TabItemViewModel()
|
||||||
|
{
|
||||||
|
Header = "Web Application Packages",
|
||||||
|
Body = new PackageManagerViewModel(this, new WebAppPackageManager())
|
||||||
|
});
|
||||||
|
}
|
||||||
|
private void OpenProjectDependencies()
|
||||||
|
{
|
||||||
|
if (Directory.Exists(CurrentProject))
|
||||||
|
{
|
||||||
|
var config = Path.Combine(CurrentProject, "cross.json");
|
||||||
|
if (File.Exists(config))
|
||||||
|
{
|
||||||
|
foreach (var item in TabItems)
|
||||||
|
{
|
||||||
|
if (item.Body is AddProjectReferenceViewModel vm)
|
||||||
|
{
|
||||||
|
if (vm.ProjectDirectory == CurrentProject)
|
||||||
|
{
|
||||||
|
SelectedTab = item;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AddTab(new TabItemViewModel()
|
||||||
|
{
|
||||||
|
Header = "Project Dependencies (folders)",
|
||||||
|
Body = new AddProjectReferenceViewModel(CurrentProject)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
private void OpenProjectPackages()
|
private void OpenProjectPackages()
|
||||||
{
|
{
|
||||||
if (Directory.Exists(CurrentProject))
|
if (Directory.Exists(CurrentProject))
|
||||||
@@ -185,7 +523,7 @@ public partial class MainWindowViewModel : ViewModelBase
|
|||||||
|
|
||||||
private void OpenProjectConfig()
|
private void OpenProjectConfig()
|
||||||
{
|
{
|
||||||
|
|
||||||
if (Directory.Exists(CurrentProject))
|
if (Directory.Exists(CurrentProject))
|
||||||
{
|
{
|
||||||
var config = Path.Combine(CurrentProject, "cross.json");
|
var config = Path.Combine(CurrentProject, "cross.json");
|
||||||
@@ -200,12 +538,23 @@ public partial class MainWindowViewModel : ViewModelBase
|
|||||||
TabItemViewModel vm = new TabItemViewModel();
|
TabItemViewModel vm = new TabItemViewModel();
|
||||||
vm.Header = "Project Configuration";
|
vm.Header = "Project Configuration";
|
||||||
var pcm = new ProjectConfigurationViewModel(config, vm);
|
var pcm = new ProjectConfigurationViewModel(config, vm);
|
||||||
|
|
||||||
vm.Body = pcm;
|
vm.Body = pcm;
|
||||||
|
|
||||||
AddTab(vm);
|
AddTab(vm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
[RelayCommand]
|
||||||
|
private async Task ReferenceAsync()
|
||||||
|
{
|
||||||
|
await CrossLangShell.RunCommandAsync(Environment.CurrentDirectory, "crosslang", "docs", "--reference");
|
||||||
|
var refFile = Path.Combine(CrossLangShell.CrossLangConfigDirectory, "Reference.crvm");
|
||||||
|
Console.WriteLine(refFile);
|
||||||
|
if(File.Exists(refFile))
|
||||||
|
{
|
||||||
|
OpenFile(refFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static string[] FILE_EXTS = new string[]{
|
static string[] FILE_EXTS = new string[]{
|
||||||
".tcross",
|
".tcross",
|
||||||
@@ -232,12 +581,17 @@ public partial class MainWindowViewModel : ViewModelBase
|
|||||||
public void OpenFile(string path)
|
public void OpenFile(string path)
|
||||||
{
|
{
|
||||||
bool isValid = false;
|
bool isValid = false;
|
||||||
|
string ext = Path.GetExtension(path).ToLower();
|
||||||
foreach (var item in FILE_EXTS)
|
foreach (var item in FILE_EXTS)
|
||||||
{
|
{
|
||||||
if (Path.GetExtension(path).ToLower() == item)
|
if (ext == item)
|
||||||
isValid = true;
|
isValid = true;
|
||||||
}
|
}
|
||||||
if (!isValid) return;
|
if (!isValid)
|
||||||
|
{
|
||||||
|
OpenOtherFile(path, ext);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var item in TabItems)
|
foreach (var item in TabItems)
|
||||||
{
|
{
|
||||||
@@ -255,10 +609,39 @@ public partial class MainWindowViewModel : ViewModelBase
|
|||||||
Header = Path.GetFileName(path),
|
Header = Path.GetFileName(path),
|
||||||
|
|
||||||
};
|
};
|
||||||
tab.Body = new FileEditorViewModel(path,tab);
|
tab.Body = new FileEditorViewModel(path, tab);
|
||||||
AddTab(tab);
|
AddTab(tab);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OpenOtherFile(string path, string ext)
|
||||||
|
{
|
||||||
|
if (ext == ".crvm")
|
||||||
|
{
|
||||||
|
foreach (var item in TabItems)
|
||||||
|
{
|
||||||
|
if (item.Body is CRVMViewerViewModel model)
|
||||||
|
{
|
||||||
|
if (model.FilePath == path)
|
||||||
|
{
|
||||||
|
SelectedTab = item;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var tab = new TabItemViewModel()
|
||||||
|
{
|
||||||
|
Header = Path.GetFileName(path),
|
||||||
|
Body = new CRVMViewerViewModel(path)
|
||||||
|
};
|
||||||
|
|
||||||
|
AddTab(tab);
|
||||||
|
}catch(Exception ex) { Console.WriteLine(ex); }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
private TabItemViewModel? _selectedTab = null;
|
private TabItemViewModel? _selectedTab = null;
|
||||||
private void AddTab(TabItemViewModel item)
|
private void AddTab(TabItemViewModel item)
|
||||||
@@ -337,13 +720,57 @@ public partial class MainWindowViewModel : ViewModelBase
|
|||||||
SelectedTab?.Save();
|
SelectedTab?.Save();
|
||||||
}
|
}
|
||||||
[RelayCommand]
|
[RelayCommand]
|
||||||
private void SaveAll()
|
public void SaveAll()
|
||||||
{
|
{
|
||||||
foreach (var tab in TabItems)
|
foreach (var tab in TabItems)
|
||||||
{
|
{
|
||||||
tab.Save();
|
tab.Save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
private void AddPackage()
|
||||||
|
{
|
||||||
|
if (Directory.Exists(CurrentProject))
|
||||||
|
{
|
||||||
|
var conf = Path.Combine(CurrentProject, "cross.json");
|
||||||
|
if (File.Exists(conf))
|
||||||
|
{
|
||||||
|
OpenProjectPackages();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[RelayCommand]
|
||||||
|
private async Task PublishAsync()
|
||||||
|
{
|
||||||
|
SaveAll();
|
||||||
|
if(Directory.Exists(CurrentProject))
|
||||||
|
await WeakReferenceMessenger.Default.Send(new PublishMessage(CurrentProject));
|
||||||
|
}
|
||||||
|
[RelayCommand]
|
||||||
|
private async Task PushPackageAsync()
|
||||||
|
{
|
||||||
|
SaveAll();
|
||||||
|
if (Directory.Exists(CurrentProject))
|
||||||
|
{
|
||||||
|
var box = MessageBoxManager
|
||||||
|
.GetMessageBoxStandard("Push Package Confirmation", $"Are you sure you want to push the package?",
|
||||||
|
ButtonEnum.YesNo, Icon.Question);
|
||||||
|
var msg = await WeakReferenceMessenger.Default.Send<GetWindowMessage>();
|
||||||
|
if (msg is not null && await box.ShowWindowDialogAsync(msg) == ButtonResult.Yes)
|
||||||
|
|
||||||
|
CrossLangShell.PushProjectInFolder(CurrentProject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class RecoveryConfig
|
||||||
|
{
|
||||||
|
public DateTime Date { get; set; }
|
||||||
|
|
||||||
|
public string ProjectDirectory { get; set; } = "";
|
||||||
|
|
||||||
|
public bool HasRecovery { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public partial class NewTabViewModel : ViewModelBase
|
public partial class NewTabViewModel : ViewModelBase
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Avalonia.Markup.Xaml.Templates;
|
using Avalonia.Markup.Xaml.Templates;
|
||||||
using Avalonia.Media;
|
using Avalonia.Media;
|
||||||
|
using Avalonia.Platform.Storage;
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
using CommunityToolkit.Mvvm.Input;
|
using CommunityToolkit.Mvvm.Input;
|
||||||
using CommunityToolkit.Mvvm.Messaging;
|
using CommunityToolkit.Mvvm.Messaging;
|
||||||
@@ -85,6 +87,20 @@ public partial class NewProjectDialogViewModel : ViewModelBase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
[RelayCommand]
|
||||||
|
public async Task BrowseAsync()
|
||||||
|
{
|
||||||
|
var window = await WeakReferenceMessenger.Default.Send<GetWindowMessage>();
|
||||||
|
|
||||||
|
|
||||||
|
var res = await window.StorageProvider.OpenFolderPickerAsync(new Avalonia.Platform.Storage.FolderPickerOpenOptions() { Title = "Pick Project Parent Folder" });
|
||||||
|
if (res.Count != 0)
|
||||||
|
{
|
||||||
|
string? path = res[0].TryGetLocalPath();
|
||||||
|
if(!string.IsNullOrWhiteSpace(path))
|
||||||
|
this.ParentDirectory = path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[RelayCommand]
|
[RelayCommand]
|
||||||
private void OK()
|
private void OK()
|
||||||
@@ -111,7 +127,7 @@ public partial class CrossLangTemplate(string name,CrossLangFile file) : Observa
|
|||||||
{
|
{
|
||||||
|
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
private string _name = file.GetTemplatePrettyName();
|
private string _name = file.GetPrettyName();
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
private IImage _icon = file.GetIcon(64);
|
private IImage _icon = file.GetIcon(64);
|
||||||
|
|
||||||
|
|||||||
@@ -49,12 +49,12 @@ public partial class PackageManagerViewModel : ViewModelBase
|
|||||||
foreach(var svr in CrossLangShell.GetServers())
|
foreach(var svr in CrossLangShell.GetServers())
|
||||||
this.Servers.Add(svr);
|
this.Servers.Add(svr);
|
||||||
}
|
}
|
||||||
|
//
|
||||||
[RelayCommand]
|
[RelayCommand]
|
||||||
private async Task SearchPackagesAsync()
|
private async Task SearchPackagesAsync()
|
||||||
{
|
{
|
||||||
var svr = Servers[ServerIndex].TrimEnd('/');
|
var svr = Servers[ServerIndex].TrimEnd('/');
|
||||||
var body = await Main.Client.GetStringAsync($"{svr}/api/v1/search?q={HttpUtility.UrlEncode(Search)}&filter={HttpUtility.UrlEncode(Packages.Filter)}&offset={Page-1}&limit=20");
|
var body = await Main.Client.GetStringAsync($"{svr}/api/v1/search?q={HttpUtility.UrlEncode(Search)}&type={HttpUtility.UrlEncode(Packages.Filter)}&offset={Page-1}&limit=20");
|
||||||
var res = JsonConvert.DeserializeObject<SearchResult>(body);
|
var res = JsonConvert.DeserializeObject<SearchResult>(body);
|
||||||
PackageList.Clear();
|
PackageList.Clear();
|
||||||
if (res is not null)
|
if (res is not null)
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ public partial class ProjectConfigurationViewModel : ViewModelBase, ISavable
|
|||||||
TabItemViewModel tab;
|
TabItemViewModel tab;
|
||||||
public string FilePath { get; }
|
public string FilePath { get; }
|
||||||
bool _modified = false;
|
bool _modified = false;
|
||||||
private bool Modified
|
public bool Modified
|
||||||
{
|
{
|
||||||
get => _modified;
|
get => _modified;
|
||||||
set
|
set
|
||||||
@@ -56,8 +56,8 @@ public partial class ProjectConfigurationViewModel : ViewModelBase, ISavable
|
|||||||
|
|
||||||
string _license;
|
string _license;
|
||||||
|
|
||||||
string _templatename;
|
string _shortname;
|
||||||
string _templatenamepretty;
|
string _shortnamepretty;
|
||||||
|
|
||||||
string _description;
|
string _description;
|
||||||
|
|
||||||
@@ -130,22 +130,22 @@ public partial class ProjectConfigurationViewModel : ViewModelBase, ISavable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string TemplateName
|
public string ShortName
|
||||||
{
|
{
|
||||||
get => _templatename;
|
get => _shortname;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
Modified = true;
|
Modified = true;
|
||||||
SetProperty(ref _templatename, value, nameof(TemplateName));
|
SetProperty(ref _shortname, value, nameof(ShortName));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public string TemplateNamePretty
|
public string ShortNamePretty
|
||||||
{
|
{
|
||||||
get => _templatenamepretty;
|
get => _shortnamepretty;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
Modified = true;
|
Modified = true;
|
||||||
SetProperty(ref _templatenamepretty, value, nameof(TemplateNamePretty));
|
SetProperty(ref _shortnamepretty, value, nameof(ShortNamePretty));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public string Description
|
public string Description
|
||||||
@@ -183,8 +183,8 @@ public partial class ProjectConfigurationViewModel : ViewModelBase, ISavable
|
|||||||
_homepage = config?.Info?.HomePage ?? "";
|
_homepage = config?.Info?.HomePage ?? "";
|
||||||
_maintainer = config?.Info?.Maintainer ?? "";
|
_maintainer = config?.Info?.Maintainer ?? "";
|
||||||
_license = config?.Info?.License ?? "";
|
_license = config?.Info?.License ?? "";
|
||||||
_templatename = config?.Info?.TemplateName ?? "";
|
_shortname = config?.Info?.ShortName ?? "";
|
||||||
_templatenamepretty = config?.Info?.TemplateNamePretty ?? "";
|
_shortnamepretty = config?.Info?.ShortNamePretty ?? "";
|
||||||
_type = Array.IndexOf(CrossLangShell.ProjectTypes, config?.Info?.Type ?? "console");
|
_type = Array.IndexOf(CrossLangShell.ProjectTypes, config?.Info?.Type ?? "console");
|
||||||
_type = _type == -1 ? 0 : _type;
|
_type = _type == -1 ? 0 : _type;
|
||||||
_description = config?.Info?.Description ?? "";
|
_description = config?.Info?.Description ?? "";
|
||||||
@@ -193,6 +193,12 @@ public partial class ProjectConfigurationViewModel : ViewModelBase, ISavable
|
|||||||
[RelayCommand]
|
[RelayCommand]
|
||||||
|
|
||||||
public void Save()
|
public void Save()
|
||||||
|
{
|
||||||
|
SaveRecovery(FilePath);
|
||||||
|
Modified = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SaveRecovery(string path)
|
||||||
{
|
{
|
||||||
var config = JsonConvert.DeserializeObject<CrossLangConfig>(File.ReadAllText(FilePath)) ?? new CrossLangConfig();
|
var config = JsonConvert.DeserializeObject<CrossLangConfig>(File.ReadAllText(FilePath)) ?? new CrossLangConfig();
|
||||||
config.Name = Name;
|
config.Name = Name;
|
||||||
@@ -207,13 +213,12 @@ public partial class ProjectConfigurationViewModel : ViewModelBase, ISavable
|
|||||||
config.Info.License = string.IsNullOrWhiteSpace(License) ? null : License;
|
config.Info.License = string.IsNullOrWhiteSpace(License) ? null : License;
|
||||||
config.Info.Maintainer = string.IsNullOrWhiteSpace(Maintainer) ? null : Maintainer;
|
config.Info.Maintainer = string.IsNullOrWhiteSpace(Maintainer) ? null : Maintainer;
|
||||||
config.Info.Repoository = string.IsNullOrWhiteSpace(Repository) ? null : Repository;
|
config.Info.Repoository = string.IsNullOrWhiteSpace(Repository) ? null : Repository;
|
||||||
config.Info.TemplateName = string.IsNullOrWhiteSpace(TemplateName) ? null : TemplateName;
|
config.Info.ShortName = string.IsNullOrWhiteSpace(ShortName) ? null : ShortName;
|
||||||
config.Info.TemplateNamePretty = string.IsNullOrWhiteSpace(TemplateNamePretty) ? null : TemplateNamePretty;
|
config.Info.ShortNamePretty = string.IsNullOrWhiteSpace(ShortNamePretty) ? null : ShortNamePretty;
|
||||||
config.Info.Type = CrossLangShell.ProjectTypes[Type];
|
config.Info.Type = CrossLangShell.ProjectTypes[Type];
|
||||||
File.WriteAllText(FilePath, JsonConvert.SerializeObject(config, Formatting.Indented, new JsonSerializerSettings()
|
File.WriteAllText(path, JsonConvert.SerializeObject(config, Formatting.Indented, new JsonSerializerSettings()
|
||||||
{
|
{
|
||||||
NullValueHandling = NullValueHandling.Ignore
|
NullValueHandling = NullValueHandling.Ignore
|
||||||
}));
|
}));
|
||||||
Modified = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
279
ViewModels/PublishDialogViewModel.cs
Normal file
279
ViewModels/PublishDialogViewModel.cs
Normal file
@@ -0,0 +1,279 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Web;
|
||||||
|
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;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using ICSharpCode.SharpZipLib.Zip;
|
||||||
|
using ICSharpCode.SharpZipLib.Tar;
|
||||||
|
using ICSharpCode.SharpZipLib.GZip;
|
||||||
|
using ICSharpCode.SharpZipLib.BZip2;
|
||||||
|
using System.Text;
|
||||||
|
using Avalonia.Platform.Storage;
|
||||||
|
|
||||||
|
namespace CrossLangDevStudio.ViewModels;
|
||||||
|
|
||||||
|
public partial class PublishDialogViewModel : ViewModelBase
|
||||||
|
{
|
||||||
|
public string Path { get; }
|
||||||
|
public PublishDialogViewModel(string path)
|
||||||
|
{
|
||||||
|
Path = path;
|
||||||
|
foreach (var item in CrossLangShell.GetServers())
|
||||||
|
{
|
||||||
|
Servers.Add(item);
|
||||||
|
}
|
||||||
|
Targets.Add(new Target("copy", "Just Copy"));
|
||||||
|
Targets.Add(new Target("crvm", "Merge"));
|
||||||
|
Targets.Add(new Target("cmake", "CMake"));
|
||||||
|
Targets.Add(new Target("header", "C++ Header"));
|
||||||
|
this.TargetIndex = 0;
|
||||||
|
}
|
||||||
|
[ObservableProperty]
|
||||||
|
private string _prefix = "Tesses.CrossLang.Runtime";
|
||||||
|
|
||||||
|
public ObservableCollection<string> Servers { get; } = new ObservableCollection<string>();
|
||||||
|
[ObservableProperty]
|
||||||
|
private int _serverIndex = 0;
|
||||||
|
public ObservableCollection<Target> Targets { get; } = new ObservableCollection<Target>();
|
||||||
|
[ObservableProperty]
|
||||||
|
private int _targetIndex = 0;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private string _output = "";
|
||||||
|
int _ot=0;
|
||||||
|
public int OutputType
|
||||||
|
{
|
||||||
|
get => _ot;
|
||||||
|
set {
|
||||||
|
_ot = value;
|
||||||
|
switch(value)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
OutputLabel = "Directory To Publish To (Optional)";
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
OutputLabel = "Zip Path";
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
case 3:
|
||||||
|
case 4:
|
||||||
|
OutputLabel = "Tar Path";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private string _outputLabel = "Directory To Publish To (Optional)";
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
private async Task BrowseAsync()
|
||||||
|
{
|
||||||
|
var window = await WeakReferenceMessenger.Default.Send<GetWindowMessage>();
|
||||||
|
|
||||||
|
if (OutputType == 0)
|
||||||
|
{
|
||||||
|
var res = await window.StorageProvider.OpenFolderPickerAsync(new Avalonia.Platform.Storage.FolderPickerOpenOptions() { Title = "Pick publish folder" });
|
||||||
|
if (res.Count != 0)
|
||||||
|
{
|
||||||
|
string? path = res[0].TryGetLocalPath();
|
||||||
|
if (!string.IsNullOrWhiteSpace(path))
|
||||||
|
this.Output = path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string ext = "zip";
|
||||||
|
switch(OutputType)
|
||||||
|
{
|
||||||
|
case 2:
|
||||||
|
ext = "tar";
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
ext = "tar.gz";
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
ext = "tar.bz2";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
var res = await window.StorageProvider.SaveFilePickerAsync(new Avalonia.Platform.Storage.FilePickerSaveOptions() { Title = $"Save {ext}", DefaultExtension = $".{ext}" , FileTypeChoices = [new FilePickerFileType(ext.ToUpper()){ Patterns =[$".{ext}"]}]});
|
||||||
|
if (res is not null)
|
||||||
|
{
|
||||||
|
string? path = res.TryGetLocalPath();
|
||||||
|
if (!string.IsNullOrWhiteSpace(path))
|
||||||
|
this.Output = path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
private async Task LoadAsync()
|
||||||
|
{
|
||||||
|
Targets.Clear();
|
||||||
|
Targets.Add(new Target("copy", "Just Copy"));
|
||||||
|
Targets.Add(new Target("crvm", "Merge"));
|
||||||
|
Targets.Add(new Target("cmake", "CMake"));
|
||||||
|
Targets.Add(new Target("header", "C++ Header"));
|
||||||
|
this.TargetIndex = 0;
|
||||||
|
if (ServerIndex >= 0 && ServerIndex < this.Servers.Count)
|
||||||
|
{
|
||||||
|
string url = $"{this.Servers[ServerIndex].TrimEnd('/')}/api/v1/search?type=archive";
|
||||||
|
if (!string.IsNullOrWhiteSpace(Prefix))
|
||||||
|
{
|
||||||
|
url = $"{url}&q={HttpUtility.UrlEncode(Prefix.TrimEnd('.'))}.";
|
||||||
|
}
|
||||||
|
var window = await WeakReferenceMessenger.Default.Send(new GetWindowMessage());
|
||||||
|
if (window is not null && window.DataContext is MainWindowViewModel mwvm)
|
||||||
|
{
|
||||||
|
int page = 0;
|
||||||
|
bool hadany = false;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
var body = await mwvm.Client.GetStringAsync($"{url}&offset={page}");
|
||||||
|
page++;
|
||||||
|
var res = JsonConvert.DeserializeObject<PackageManagerViewModel.SearchResult>(body);
|
||||||
|
if (res is not null)
|
||||||
|
{
|
||||||
|
hadany = res.Packages.Count > 0;
|
||||||
|
foreach (var item in res.Packages)
|
||||||
|
{
|
||||||
|
string name = item.Name;
|
||||||
|
if (!string.IsNullOrWhiteSpace(Prefix))
|
||||||
|
{
|
||||||
|
int prefixLen = Prefix.TrimEnd('.').Length + 1;
|
||||||
|
name = name.Substring(prefixLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
Targets.Add(new Target(name, name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (hadany);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
private async Task PublishAsync()
|
||||||
|
{
|
||||||
|
|
||||||
|
string ident = Targets[TargetIndex].Real;
|
||||||
|
await CrossLangShell.PublishAsync(Path, ident, Prefix, OutputType == 0 ? Output : "");
|
||||||
|
|
||||||
|
void Tar(Stream strm)
|
||||||
|
{
|
||||||
|
|
||||||
|
string dir = System.IO.Path.Combine(Path, "publish", ident);
|
||||||
|
|
||||||
|
|
||||||
|
using (var tarArchive = TarArchive.CreateOutputTarArchive(strm, Encoding.UTF8))
|
||||||
|
{
|
||||||
|
tarArchive.RootPath = System.IO.Path.DirectorySeparatorChar == '/' ? dir : dir.Replace('\\', '/');
|
||||||
|
if (tarArchive.RootPath.EndsWith("/"))
|
||||||
|
tarArchive.RootPath = tarArchive.RootPath.Remove(tarArchive.RootPath.Length - 1);
|
||||||
|
|
||||||
|
DirectoryContents(tarArchive, dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
TarEntry ent = TarEntry.CreateEntryFromFile();
|
||||||
|
ent.TarHeader.Mode = 0755;
|
||||||
|
ent.TarHeader.UserId = 1000;
|
||||||
|
ent.TarHeader.GroupId = 1000;
|
||||||
|
*/
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (OutputType > 0)
|
||||||
|
{
|
||||||
|
switch (OutputType)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
FastZip z = new FastZip();
|
||||||
|
z.CreateZip(Output, System.IO.Path.Combine(Path, "publish", ident), true, null);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
using (var strm = File.Create(Output))
|
||||||
|
Tar(strm);
|
||||||
|
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
{
|
||||||
|
using (var strm = File.Create(Output))
|
||||||
|
{
|
||||||
|
using (var gz = new GZipOutputStream(strm))
|
||||||
|
Tar(gz);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
{
|
||||||
|
using (var strm = File.Create(Output))
|
||||||
|
{
|
||||||
|
using (var bzip2 = new BZip2OutputStream(strm))
|
||||||
|
Tar(bzip2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ = WeakReferenceMessenger.Default.Send(new PublishCloseMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
private void Cancel()
|
||||||
|
{
|
||||||
|
WeakReferenceMessenger.Default.Send(new PublishCloseMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DirectoryContents(TarArchive tarArchive, string src)
|
||||||
|
{
|
||||||
|
TarEntry tarEntry = TarEntry.CreateEntryFromFile(src);
|
||||||
|
tarArchive.WriteEntry(tarEntry, false);
|
||||||
|
|
||||||
|
// Write each file to the tar.
|
||||||
|
string[] filenames = Directory.GetFiles(src);
|
||||||
|
foreach (string filename in filenames)
|
||||||
|
{
|
||||||
|
tarEntry = TarEntry.CreateEntryFromFile(filename);
|
||||||
|
|
||||||
|
tarEntry.TarHeader.UserId = 1000;
|
||||||
|
tarEntry.TarHeader.GroupId = 1000;
|
||||||
|
tarArchive.WriteEntry(tarEntry, true);
|
||||||
|
|
||||||
|
}
|
||||||
|
string[] directories = Directory.GetDirectories(src);
|
||||||
|
foreach (string directory in directories)
|
||||||
|
DirectoryContents(tarArchive, directory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Target(string real, string pretty)
|
||||||
|
{
|
||||||
|
public string Real => real;
|
||||||
|
|
||||||
|
public string Pretty => pretty;
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return Pretty;
|
||||||
|
}
|
||||||
|
}
|
||||||
43
Views/AddProjectReferenceView.axaml
Normal file
43
Views/AddProjectReferenceView.axaml
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
<UserControl xmlns="https://github.com/avaloniaui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:vm="clr-namespace:CrossLangDevStudio.ViewModels"
|
||||||
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
|
x:Class="CrossLangDevStudio.Views.AddProjectReferenceView"
|
||||||
|
x:DataType="vm:AddProjectReferenceViewModel">
|
||||||
|
<Design.DataContext>
|
||||||
|
<!-- This only sets the DataContext for the previewer in an IDE,
|
||||||
|
to set the actual DataContext for runtime, set the DataContext property in code (look at App.axaml.cs) -->
|
||||||
|
<vm:AddProjectReferenceViewModel />
|
||||||
|
</Design.DataContext>
|
||||||
|
<Grid Margin="20">
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="*" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<ScrollViewer Grid.Row="0" HorizontalScrollBarVisibility="Auto">
|
||||||
|
<ItemsControl ItemsSource="{Binding References}">
|
||||||
|
<ItemsControl.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<Grid Margin="0 10">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<TextBlock Grid.Column="0" Text="{Binding Path}" />
|
||||||
|
<Button Grid.Column="1" Content="Remove" Command="{Binding RemoveCommand}" />
|
||||||
|
</Grid>
|
||||||
|
</DataTemplate>
|
||||||
|
</ItemsControl.ItemTemplate>
|
||||||
|
</ItemsControl>
|
||||||
|
</ScrollViewer>
|
||||||
|
<Grid Grid.Row="1">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Button Grid.Column="1" Content="Add" Command="{Binding AddProjectCommand}" />
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</UserControl>
|
||||||
14
Views/AddProjectReferenceView.axaml.cs
Normal file
14
Views/AddProjectReferenceView.axaml.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
using Avalonia.Controls;
|
||||||
|
using AvaloniaEdit;
|
||||||
|
using CrossLangDevStudio.ViewModels;
|
||||||
|
|
||||||
|
namespace CrossLangDevStudio.Views;
|
||||||
|
|
||||||
|
public partial class AddProjectReferenceView : UserControl
|
||||||
|
{
|
||||||
|
public AddProjectReferenceView()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
75
Views/CRVMViewerView.axaml
Normal file
75
Views/CRVMViewerView.axaml
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
<UserControl xmlns="https://github.com/avaloniaui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:vm="clr-namespace:CrossLangDevStudio.ViewModels"
|
||||||
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
|
x:Class="CrossLangDevStudio.Views.CRVMViewerView"
|
||||||
|
x:DataType="vm:CRVMViewerViewModel">
|
||||||
|
<Design.DataContext>
|
||||||
|
<!-- This only sets the DataContext for the previewer in an IDE,
|
||||||
|
to set the actual DataContext for runtime, set the DataContext property in code (look at App.axaml.cs) -->
|
||||||
|
<vm:CRVMViewerViewModel />
|
||||||
|
</Design.DataContext>
|
||||||
|
<ScrollViewer>
|
||||||
|
<StackPanel Margin="20">
|
||||||
|
<TextBlock FontSize="42" Margin="0 5">Functions:</TextBlock>
|
||||||
|
<ItemsControl ItemsSource="{Binding Functions}" >
|
||||||
|
<ItemsControl.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<TextBlock>
|
||||||
|
<Run FontSize="24" Foreground="#6A9955" Text="{Binding Documentation}" />
|
||||||
|
<LineBreak />
|
||||||
|
<Run FontSize="24" Foreground="#569CD6" Text="func " />
|
||||||
|
<Run FontSize="24" Foreground="#DCDCAA" Text="{Binding Name}" />
|
||||||
|
<Run FontSize="24" Foreground="#C586C0" Text="(" />
|
||||||
|
<Run FontSize="24" Foreground="#CCCCCC" Text="{Binding Args}" />
|
||||||
|
<Run FontSize="24" Foreground="#C586C0" Text=")" />
|
||||||
|
</TextBlock>
|
||||||
|
</DataTemplate>
|
||||||
|
</ItemsControl.ItemTemplate>
|
||||||
|
</ItemsControl>
|
||||||
|
<TextBlock FontSize="42" Margin="0 5">Classes:</TextBlock>
|
||||||
|
<ItemsControl ItemsSource="{Binding Classes}" >
|
||||||
|
<ItemsControl.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<StackPanel>
|
||||||
|
<TextBlock>
|
||||||
|
<Run FontSize="24" Foreground="#6A9955" Text="{Binding Documentation}" />
|
||||||
|
<LineBreak />
|
||||||
|
<Run FontSize="24" Foreground="#569CD6" Text="class " />
|
||||||
|
<Run FontSize="24" Foreground="#4EC9B0" Text="{Binding Name}" />
|
||||||
|
<Run FontSize="24" Foreground="#CCCCCC" Text="{Binding InheritsColon}" />
|
||||||
|
<Run FontSize="24" Foreground="#4EC9B0" Text="{Binding Inherits}" />
|
||||||
|
<Run FontSize="24" Foreground="#CCCCCC" Text=" {" />
|
||||||
|
</TextBlock>
|
||||||
|
|
||||||
|
<ItemsControl ItemsSource="{Binding Entries}" >
|
||||||
|
<ItemsControl.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<TextBlock>
|
||||||
|
<LineBreak />
|
||||||
|
<Run FontSize="24" Foreground="#6A9955" Text="{Binding Documentation}" />
|
||||||
|
<LineBreak />
|
||||||
|
<Run FontSize="24" Foreground="#569CD6" Text="{Binding Modifiers}" />
|
||||||
|
<Run FontSize="24" Foreground="{Binding NameColor}" Text="{Binding Name}" />
|
||||||
|
<Run FontSize="24" Foreground="{Binding LeftParenColor}" Text="{Binding LeftParen}" />
|
||||||
|
<Run FontSize="24" Foreground="#CCCCCC" Text="{Binding Args}" />
|
||||||
|
<Run FontSize="24" Foreground="#C586C0" Text="{Binding RightParen}" />
|
||||||
|
</TextBlock>
|
||||||
|
</DataTemplate>
|
||||||
|
</ItemsControl.ItemTemplate>
|
||||||
|
</ItemsControl>
|
||||||
|
<TextBlock>
|
||||||
|
<LineBreak />
|
||||||
|
<Run FontSize="24" Foreground="#CCCCCC" Text="}" />
|
||||||
|
</TextBlock>
|
||||||
|
</StackPanel>
|
||||||
|
</DataTemplate>
|
||||||
|
</ItemsControl.ItemTemplate>
|
||||||
|
</ItemsControl>
|
||||||
|
</StackPanel>
|
||||||
|
</ScrollViewer>
|
||||||
|
</UserControl>
|
||||||
|
|
||||||
|
<!--4EC9B0-->
|
||||||
14
Views/CRVMViewerView.axaml.cs
Normal file
14
Views/CRVMViewerView.axaml.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
using Avalonia.Controls;
|
||||||
|
using AvaloniaEdit;
|
||||||
|
using CrossLangDevStudio.ViewModels;
|
||||||
|
|
||||||
|
namespace CrossLangDevStudio.Views;
|
||||||
|
|
||||||
|
public partial class CRVMViewerView : UserControl
|
||||||
|
{
|
||||||
|
public CRVMViewerView()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,13 +5,15 @@
|
|||||||
xmlns:vm="clr-namespace:CrossLangDevStudio.ViewModels"
|
xmlns:vm="clr-namespace:CrossLangDevStudio.ViewModels"
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="CrossLangDevStudio.Views.FileEditorView"
|
x:Class="CrossLangDevStudio.Views.FileEditorView"
|
||||||
|
xmlns:AvaloniaEdit="clr-namespace:AvaloniaEdit;assembly=AvaloniaEdit"
|
||||||
x:DataType="vm:FileEditorViewModel">
|
x:DataType="vm:FileEditorViewModel">
|
||||||
<Design.DataContext>
|
<Design.DataContext>
|
||||||
<!-- This only sets the DataContext for the previewer in an IDE,
|
<!-- This only sets the DataContext for the previewer in an IDE,
|
||||||
to set the actual DataContext for runtime, set the DataContext property in code (look at App.axaml.cs) -->
|
to set the actual DataContext for runtime, set the DataContext property in code (look at App.axaml.cs) -->
|
||||||
<vm:FileEditorViewModel />
|
<vm:FileEditorViewModel />
|
||||||
</Design.DataContext>
|
</Design.DataContext>
|
||||||
|
|
||||||
<TextBox FontSize="24" FontFamily="{StaticResource AardvarkFont}" Text="{Binding Text}" AcceptsReturn="True" AcceptsTab="True" TextWrapping="Wrap"/>
|
|
||||||
|
<!--<TextBox FontSize="24" FontFamily="{StaticResource AardvarkFont}" Text="{Binding Text}" AcceptsReturn="True" AcceptsTab="True" TextWrapping="Wrap"/>-->
|
||||||
|
|
||||||
</UserControl>
|
</UserControl>
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
|
using AvaloniaEdit;
|
||||||
using CrossLangDevStudio.ViewModels;
|
using CrossLangDevStudio.ViewModels;
|
||||||
|
|
||||||
namespace CrossLangDevStudio.Views;
|
namespace CrossLangDevStudio.Views;
|
||||||
@@ -8,5 +9,21 @@ public partial class FileEditorView : UserControl
|
|||||||
public FileEditorView()
|
public FileEditorView()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
this.Loaded += (sender, e) =>
|
||||||
|
{
|
||||||
|
if (this.DataContext is FileEditorViewModel dc)
|
||||||
|
{
|
||||||
|
this.Content = dc.TextEditor;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.Unloaded += (sender, e) =>
|
||||||
|
{
|
||||||
|
this.Content = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -28,37 +28,38 @@
|
|||||||
<MenuItem Header="_Open Project" HotKey="Ctrl+O" Command="{Binding OpenProjectCommand}"/>
|
<MenuItem Header="_Open Project" HotKey="Ctrl+O" Command="{Binding OpenProjectCommand}"/>
|
||||||
<MenuItem Header="_Save" HotKey="Ctrl+S" Command="{Binding SaveCommand}"/>
|
<MenuItem Header="_Save" HotKey="Ctrl+S" Command="{Binding SaveCommand}"/>
|
||||||
<MenuItem Header="Save All" HotKey="Ctrl+Shift+S" Command="{Binding SaveAllCommand}"/>
|
<MenuItem Header="Save All" HotKey="Ctrl+Shift+S" Command="{Binding SaveAllCommand}"/>
|
||||||
<MenuItem Header="CrossLang Settings"/>
|
|
||||||
<Separator/>
|
<Separator/>
|
||||||
<MenuItem Header="_Exit" HotKey="Alt+F4"/>
|
<MenuItem Header="_Exit" HotKey="Alt+F4"/>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem Header="_Project">
|
<MenuItem Header="_Project">
|
||||||
<MenuItem Header="Build" Command="{Binding BuildCommand}" />
|
<MenuItem Header="Build" Command="{Binding BuildCommand}" />
|
||||||
<MenuItem Header="Build And Run" HotKey="F5" Command="{Binding BuildAndRunCommand}" />
|
<MenuItem Header="Build And Run" HotKey="F5" Command="{Binding BuildAndRunCommand}" />
|
||||||
|
<MenuItem Header="Publish" Command="{Binding PublishCommand}" />
|
||||||
<MenuItem Header="Open In File Manager" Command="{Binding OpenProjectInFileManagerCommand}" />
|
<MenuItem Header="Open In File Manager" Command="{Binding OpenProjectInFileManagerCommand}" />
|
||||||
<MenuItem Header="Open In Terminal" HotKey="CTRL+T" Command="{Binding OpenProjectInTerminalCommand}" />
|
<MenuItem Header="Open In Terminal" HotKey="CTRL+T" Command="{Binding OpenProjectInTerminalCommand}" />
|
||||||
<MenuItem Header="Refresh" HotKey="CTRL+R" Command="{Binding RefreshListingCommand}" />
|
<MenuItem Header="Refresh" HotKey="CTRL+R" Command="{Binding RefreshListingCommand}" />
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem Header="_CPKG">
|
<MenuItem Header="_CPKG">
|
||||||
<MenuItem Header="Add Package"/>
|
<MenuItem Header="Add Package" Command="{Binding AddPackageCommand}"/>
|
||||||
<MenuItem Header="Install">
|
<MenuItem Header="Install">
|
||||||
<MenuItem Header="Template"/>
|
<MenuItem Header="Template" Command="{Binding InstallTemplateCommand}"/>
|
||||||
<MenuItem Header="Tool"/>
|
<MenuItem Header="Tool" Command="{Binding InstallToolCommand}"/>
|
||||||
<MenuItem Header="Web Application"/>
|
<MenuItem Header="Web Application" Command="{Binding InstallWebAppCommand}"/>
|
||||||
<MenuItem Header="Console Application"/>
|
<MenuItem Header="Console Application" Command="{Binding InstallConsoleCommand}"/>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem Header="Push Package"/>
|
<MenuItem Header="Push Package" Command="{Binding PushPackageCommand}"/>
|
||||||
<MenuItem Header="Manage Servers"/>
|
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem Header="_Help">
|
<MenuItem Header="_Help">
|
||||||
|
|
||||||
<MenuItem Header="Welcome"/>
|
<MenuItem Header="Welcome" Command="{Binding WelcomeCommand}"/>
|
||||||
<MenuItem Header="Website"/>
|
<MenuItem Header="Website" Command="{Binding WebsiteCommand}"/>
|
||||||
<MenuItem Header="Documentation"/>
|
<MenuItem Header="Documentation" Command="{Binding DocumentationCommand}"/>
|
||||||
|
<MenuItem Header="Video Documentation" Command="{Binding VideoDocumentationCommand}" />
|
||||||
|
<MenuItem Header="Reference" Command="{Binding ReferenceCommand}" />
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
</Menu>
|
</Menu>
|
||||||
<Grid Grid.Row="1" ColumnDefinitions="300, 4, *">
|
<Grid Grid.Row="1" ColumnDefinitions="300, 4, *">
|
||||||
<TreeView Grid.Column="0" ItemsSource="{Binding ProjectFiles}" SelectedItem="{Binding SelectedProjectFile}">
|
<TreeView Grid.Column="0" ItemsSource="{Binding ProjectFiles}" SelectedItem="{Binding SelectedProjectFile}">
|
||||||
<!--Thanks to https://stackoverflow.com/a/77362693 -->
|
<!--Thanks to https://stackoverflow.com/a/77362693 -->
|
||||||
<TreeView.ItemContainerTheme>
|
<TreeView.ItemContainerTheme>
|
||||||
<ControlTheme TargetType="TreeViewItem" BasedOn="{StaticResource {x:Type TreeViewItem}}">
|
<ControlTheme TargetType="TreeViewItem" BasedOn="{StaticResource {x:Type TreeViewItem}}">
|
||||||
@@ -78,6 +79,7 @@
|
|||||||
<controls:TabsControl SelectedItem="{Binding SelectedTab}" Grid.Column="2" ItemsSource="{Binding TabItems}"
|
<controls:TabsControl SelectedItem="{Binding SelectedTab}" Grid.Column="2" ItemsSource="{Binding TabItems}"
|
||||||
NewItemFactory="{Binding NewItemFactory}"
|
NewItemFactory="{Binding NewItemFactory}"
|
||||||
LastTabClosedAction="{Binding Closed}"
|
LastTabClosedAction="{Binding Closed}"
|
||||||
|
TabClosing="{Binding ClosingTab}"
|
||||||
ShowDefaultAddButton="True"
|
ShowDefaultAddButton="True"
|
||||||
ShowDefaultCloseButton="True"
|
ShowDefaultCloseButton="True"
|
||||||
Margin="0 8 0 0"
|
Margin="0 8 0 0"
|
||||||
|
|||||||
@@ -1,21 +1,59 @@
|
|||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Platform.Storage;
|
using Avalonia.Platform.Storage;
|
||||||
|
using Avalonia.Threading;
|
||||||
using CommunityToolkit.Mvvm.Messaging;
|
using CommunityToolkit.Mvvm.Messaging;
|
||||||
using CrossLangDevStudio.Messages;
|
using CrossLangDevStudio.Messages;
|
||||||
using CrossLangDevStudio.ViewModels;
|
using CrossLangDevStudio.ViewModels;
|
||||||
|
using MsBox.Avalonia;
|
||||||
|
using MsBox.Avalonia.Enums;
|
||||||
|
using Tabalonia.Controls;
|
||||||
|
|
||||||
namespace CrossLangDevStudio.Views;
|
namespace CrossLangDevStudio.Views;
|
||||||
|
|
||||||
public partial class MainWindow : Window
|
public partial class MainWindow : Window
|
||||||
{
|
{
|
||||||
|
private async Task CloseWindowAsync(WindowClosingEventArgs e, MainWindowViewModel vm)
|
||||||
|
{
|
||||||
|
var box = MessageBoxManager
|
||||||
|
.GetMessageBoxStandard("Save?", $"You have unsaved work do you want to save?",
|
||||||
|
ButtonEnum.YesNoCancel, MsBox.Avalonia.Enums.Icon.Question);
|
||||||
|
|
||||||
|
switch (await box.ShowWindowDialogAsync(this))
|
||||||
|
{
|
||||||
|
case ButtonResult.Yes:
|
||||||
|
vm.SaveAll();
|
||||||
|
break;
|
||||||
|
case ButtonResult.Cancel:
|
||||||
|
e.Cancel = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
public MainWindow()
|
public MainWindow()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
if (Design.IsDesignMode)
|
if (Design.IsDesignMode)
|
||||||
return;
|
return;
|
||||||
|
this.Closing += (sender, e) =>
|
||||||
|
{
|
||||||
|
if (this.DataContext is MainWindowViewModel vm)
|
||||||
|
{
|
||||||
|
if (vm.HasUnsaved)
|
||||||
|
{
|
||||||
|
//thanks https://github.com/AvaloniaUI/Avalonia/issues/4810#issuecomment-704372304
|
||||||
|
using (var source = new CancellationTokenSource())
|
||||||
|
{
|
||||||
|
CloseWindowAsync(e, vm).ContinueWith(e => source.Cancel(), TaskScheduler.FromCurrentSynchronizationContext());
|
||||||
|
Dispatcher.UIThread.MainLoop(source.Token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// Whenever 'Send(new PurchaseAlbumMessage())' is called, invoke this callback on the MainWindow instance:
|
// Whenever 'Send(new PurchaseAlbumMessage())' is called, invoke this callback on the MainWindow instance:
|
||||||
WeakReferenceMessenger.Default.Register<MainWindow, NewProjectMessage>(this, static (w, m) =>
|
WeakReferenceMessenger.Default.Register<MainWindow, NewProjectMessage>(this, static (w, m) =>
|
||||||
@@ -27,6 +65,7 @@ public partial class MainWindow : Window
|
|||||||
};
|
};
|
||||||
// Show dialog window and reply with returned AlbumViewModel or null when the dialog is closed.
|
// Show dialog window and reply with returned AlbumViewModel or null when the dialog is closed.
|
||||||
m.Reply(dialog.ShowDialog<string?>(w));
|
m.Reply(dialog.ShowDialog<string?>(w));
|
||||||
|
|
||||||
});
|
});
|
||||||
WeakReferenceMessenger.Default.Register<MainWindow, InstallPackageMessage>(this, static (w, m) =>
|
WeakReferenceMessenger.Default.Register<MainWindow, InstallPackageMessage>(this, static (w, m) =>
|
||||||
{
|
{
|
||||||
@@ -42,6 +81,13 @@ public partial class MainWindow : Window
|
|||||||
m.Reply(w);
|
m.Reply(w);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
WeakReferenceMessenger.Default.Register<MainWindow, PublishMessage>(this, static (w, m) =>
|
||||||
|
{
|
||||||
|
var dialog = new PublishDialogView
|
||||||
|
{
|
||||||
|
DataContext = new PublishDialogViewModel(m.Path)
|
||||||
|
};
|
||||||
|
m.Reply(dialog.ShowDialog(w));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
to set the actual DataContext for runtime, set the DataContext property in code (look at App.axaml.cs) -->
|
to set the actual DataContext for runtime, set the DataContext property in code (look at App.axaml.cs) -->
|
||||||
<vm:NewProjectDialogViewModel/>
|
<vm:NewProjectDialogViewModel/>
|
||||||
</Design.DataContext>
|
</Design.DataContext>
|
||||||
<Grid>
|
<Grid Margin="10">
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="*"/>
|
<RowDefinition Height="*"/>
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
@@ -32,19 +32,19 @@
|
|||||||
<ColumnDefinition Width="*" />
|
<ColumnDefinition Width="*" />
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<Image Grid.Column="0" Source="{Binding Icon}" />
|
<Image Grid.Column="0" Source="{Binding Icon}" />
|
||||||
<TextBlock Grid.Column="1" Text="{Binding Name}"/>
|
<TextBlock Margin="10 0 0 0" Grid.Column="1" Text="{Binding Name}" VerticalAlignment="Center"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</ListBox.ItemTemplate>
|
</ListBox.ItemTemplate>
|
||||||
</ListBox>
|
</ListBox>
|
||||||
|
|
||||||
<Grid Grid.Row="1">
|
<Grid Grid.Row="1" Margin="0 10">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="Auto" />
|
<ColumnDefinition Width="Auto" />
|
||||||
<ColumnDefinition Width="*" />
|
<ColumnDefinition Width="*" />
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<Label Grid.Column="0" Content="Name: " />
|
<Label Grid.Column="0" Content="Name: " />
|
||||||
<TextBox Grid.Column="1" Text="{Binding Name}" />
|
<TextBox Margin="10 0 0 0" Grid.Column="1" Text="{Binding Name}" />
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid Grid.Row="2">
|
<Grid Grid.Row="2">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
@@ -53,16 +53,16 @@
|
|||||||
<ColumnDefinition Width="Auto" />
|
<ColumnDefinition Width="Auto" />
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<Label Grid.Column="0" Content="Parent Directory: " />
|
<Label Grid.Column="0" Content="Parent Directory: " />
|
||||||
<TextBox Grid.Column="1" Text="{Binding ParentDirectory}"/>
|
<TextBox Margin="10 0" Grid.Column="1" Text="{Binding ParentDirectory}"/>
|
||||||
<Button Grid.Column="2" Content="Browse..." />
|
<Button Grid.Column="2" Content="Browse..." Command="{Binding BrowseCommand}" />
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid Grid.Row="3">
|
<Grid Grid.Row="3" Margin="0 10 0 0">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="*" />
|
<ColumnDefinition Width="*" />
|
||||||
<ColumnDefinition Width="Auto" />
|
<ColumnDefinition Width="Auto" />
|
||||||
<ColumnDefinition Width="Auto" />
|
<ColumnDefinition Width="Auto" />
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<Button Grid.Column="1" Content="OK" Command="{Binding OKCommand}" />
|
<Button Margin="10 0" Grid.Column="1" Content="OK" Command="{Binding OKCommand}" />
|
||||||
<Button Grid.Column="2" Content="Cancel" Command="{Binding CancelCommand}" />
|
<Button Grid.Column="2" Content="Cancel" Command="{Binding CancelCommand}" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
to set the actual DataContext for runtime, set the DataContext property in code (look at App.axaml.cs) -->
|
to set the actual DataContext for runtime, set the DataContext property in code (look at App.axaml.cs) -->
|
||||||
<vm:PackageManagerViewModel />
|
<vm:PackageManagerViewModel />
|
||||||
</Design.DataContext>
|
</Design.DataContext>
|
||||||
<Grid>
|
<Grid Margin="20">
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="Auto" />
|
<RowDefinition Height="Auto" />
|
||||||
<RowDefinition Height="*" />
|
<RowDefinition Height="*" />
|
||||||
@@ -25,21 +25,21 @@
|
|||||||
<ColumnDefinition Width="Auto"/>
|
<ColumnDefinition Width="Auto"/>
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<TextBox Grid.Column="0" Text="{Binding Search}" Watermark="Search..." />
|
<TextBox Grid.Column="0" Text="{Binding Search}" Watermark="Search..." />
|
||||||
<ComboBox Grid.Column="1" ItemsSource="{Binding Servers}" SelectedIndex="{Binding ServerIndex}" />
|
<ComboBox Margin="20 0" Grid.Column="1" ItemsSource="{Binding Servers}" SelectedIndex="{Binding ServerIndex}" />
|
||||||
<Button Grid.Column="2" Content="Search" Command="{Binding SearchPackagesCommand}" />
|
<Button Grid.Column="2" Content="Search" Command="{Binding SearchPackagesCommand}" />
|
||||||
</Grid>
|
</Grid>
|
||||||
<ScrollViewer Grid.Row="1" HorizontalScrollBarVisibility="Auto">
|
<ScrollViewer Grid.Row="1" HorizontalScrollBarVisibility="Auto">
|
||||||
<ItemsControl ItemsSource="{Binding PackageList}">
|
<ItemsControl ItemsSource="{Binding PackageList}">
|
||||||
<ItemsControl.ItemTemplate>
|
<ItemsControl.ItemTemplate>
|
||||||
<DataTemplate>
|
<DataTemplate>
|
||||||
<Grid>
|
<Grid Margin="0 20">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="64" />
|
<ColumnDefinition Width="64" />
|
||||||
<ColumnDefinition Width="*" />
|
<ColumnDefinition Width="*" />
|
||||||
<ColumnDefinition Width="Auto" />
|
<ColumnDefinition Width="Auto" />
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<Image Grid.Column="0" Source="{Binding Icon}" />
|
<Image Grid.Column="0" Source="{Binding Icon}" />
|
||||||
<Grid Grid.Column="1">
|
<Grid Grid.Column="1" Margin="20 0">
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="Auto"/>
|
<RowDefinition Height="Auto"/>
|
||||||
<RowDefinition Height="Auto"/>
|
<RowDefinition Height="Auto"/>
|
||||||
|
|||||||
@@ -43,10 +43,10 @@
|
|||||||
<TextBox Watermark="Project Homepage" Text="{Binding Homepage}"/>
|
<TextBox Watermark="Project Homepage" Text="{Binding Homepage}"/>
|
||||||
<TextBlock Margin="0 5" >License:</TextBlock>
|
<TextBlock Margin="0 5" >License:</TextBlock>
|
||||||
<TextBox Watermark="Project License" Text="{Binding License}"/>
|
<TextBox Watermark="Project License" Text="{Binding License}"/>
|
||||||
<TextBlock Margin="0 5" >Template Name (Shown in crosslang new --list):</TextBlock>
|
<TextBlock Margin="0 5" >Short Name (Shown in crosslang new --list or tool or console name):</TextBlock>
|
||||||
<TextBox Watermark="Project Template Name" Text="{Binding TemplateName}"/>
|
<TextBox Watermark="Project Short Name" Text="{Binding ShortName}"/>
|
||||||
<TextBlock Margin="0 5" >Template Pretty Name (Shown in new project):</TextBlock>
|
<TextBlock Margin="0 5" >Short Pretty Name (Shown in new project):</TextBlock>
|
||||||
<TextBox Watermark="Project Template Pretty Name" Text="{Binding TemplateNamePretty}"/>
|
<TextBox Watermark="Project Short Pretty Name" Text="{Binding ShortNamePretty}"/>
|
||||||
<TextBlock Margin="0 15 0 5">Description:</TextBlock>
|
<TextBlock Margin="0 15 0 5">Description:</TextBlock>
|
||||||
<TextBox Height="100" Text="{Binding Description}" AcceptsReturn="True" AcceptsTab="True" TextWrapping="Wrap"/>
|
<TextBox Height="100" Text="{Binding Description}" AcceptsReturn="True" AcceptsTab="True" TextWrapping="Wrap"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|||||||
79
Views/PublishDialogView.axaml
Normal file
79
Views/PublishDialogView.axaml
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
<Window xmlns="https://github.com/avaloniaui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:vm="using:CrossLangDevStudio.ViewModels"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
|
Width="640"
|
||||||
|
Height="480"
|
||||||
|
WindowStartupLocation="CenterOwner"
|
||||||
|
x:Class="CrossLangDevStudio.Views.PublishDialogView"
|
||||||
|
x:DataType="vm:PublishDialogViewModel"
|
||||||
|
Icon="/Assets/crosslang.ico"
|
||||||
|
Title="Publish">
|
||||||
|
<Design.DataContext>
|
||||||
|
<!-- This only sets the DataContext for the previewer in an IDE,
|
||||||
|
to set the actual DataContext for runtime, set the DataContext property in code (look at App.axaml.cs) -->
|
||||||
|
<vm:PublishDialogViewModel/>
|
||||||
|
</Design.DataContext>
|
||||||
|
|
||||||
|
<Grid Margin="20">
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="*" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
|
<Label Margin="0 5" Grid.Row="0" Content="Package Prefix" />
|
||||||
|
<TextBox Grid.Row="1" Text="{Binding Prefix}" />
|
||||||
|
<Label Margin="0 5" Grid.Row="2" Content="Server (click load even if correct and if package prefix is changed)" />
|
||||||
|
<Grid Grid.Row="3">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<ComboBox Grid.Column="0" ItemsSource="{Binding Servers}" SelectedIndex="{Binding ServerIndex}" HorizontalAlignment="Stretch" />
|
||||||
|
<Button Grid.Column="1" Content="Load" Command="{Binding LoadCommand}" />
|
||||||
|
</Grid>
|
||||||
|
<Label Margin="0 5" Grid.Row="4" Content="Target" />
|
||||||
|
<ComboBox Grid.Row="5" ItemsSource="{Binding Targets}" SelectedIndex="{Binding TargetIndex}" HorizontalAlignment="Stretch" />
|
||||||
|
<Label Margin="0 5" Grid.Row="6" Content="Output type" />
|
||||||
|
<ComboBox Grid.Row="7" SelectedIndex="{Binding OutputType}" HorizontalAlignment="Stretch">
|
||||||
|
<ComboBoxItem>Directory</ComboBoxItem>
|
||||||
|
<ComboBoxItem>ZIP</ComboBoxItem>
|
||||||
|
<ComboBoxItem>TAR</ComboBoxItem>
|
||||||
|
<ComboBoxItem>TAR.GZ</ComboBoxItem>
|
||||||
|
<ComboBoxItem>TAR.BZ2</ComboBoxItem>
|
||||||
|
</ComboBox>
|
||||||
|
|
||||||
|
<Label Margin="0 5" Grid.Row="8" Content="{Binding OutputLabel}" />
|
||||||
|
<Grid Grid.Row="9">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
|
<TextBox Grid.Column="0" Text="{Binding Output}" />
|
||||||
|
<Button Grid.Column="1" Content="Browse" Command="{Binding BrowseCommand}" />
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Grid Grid.Row="11">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Button Grid.Column="1" Content="Publish" Command="{Binding PublishCommand}" Margin="0 0 5 0"/>
|
||||||
|
<Button Grid.Column="2" Content="Cancel" Command="{Binding CancelCommand}"/>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Window>
|
||||||
21
Views/PublishDialogView.axaml.cs
Normal file
21
Views/PublishDialogView.axaml.cs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
using System.Diagnostics;
|
||||||
|
using Avalonia.Controls;
|
||||||
|
using CommunityToolkit.Mvvm.Messaging;
|
||||||
|
using CrossLangDevStudio.Messages;
|
||||||
|
|
||||||
|
namespace CrossLangDevStudio.Views;
|
||||||
|
|
||||||
|
public partial class PublishDialogView : Window
|
||||||
|
{
|
||||||
|
public PublishDialogView()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
if (Design.IsDesignMode) return;
|
||||||
|
|
||||||
|
WeakReferenceMessenger.Default.Register<PublishDialogView, PublishCloseMessage>(this, static (w, m) =>
|
||||||
|
{
|
||||||
|
w.Close(false);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user