mirror of
https://onedev.site.tesses.net/crosslang/crosslangdevstudio
synced 2026-02-08 09:15:45 +00:00
New dev build
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -3,3 +3,4 @@ bin
|
||||
obj
|
||||
out
|
||||
build
|
||||
Installing
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 66 KiB |
BIN
Assets/crosslang.png
Normal file
BIN
Assets/crosslang.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.7 KiB |
@@ -6,6 +6,7 @@
|
||||
<BuiltInComInteropSupport>true</BuiltInComInteropSupport>
|
||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
|
||||
<ApplicationIcon>Assets\crosslang.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -26,6 +27,7 @@
|
||||
</PackageReference>
|
||||
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.1" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="SkiaSharp.NativeAssets.Linux.NoDependencies" Version="3.119.0" />
|
||||
<PackageReference Include="Tabalonia" Version="0.10.7" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
22
CrossLangDevStudio.sln
Normal file
22
CrossLangDevStudio.sln
Normal file
@@ -0,0 +1,22 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.0.31903.59
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CrossLangDevStudio", "CrossLangDevStudio.csproj", "{07F003F4-ED31-462B-8711-5BE508A4CD35}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{07F003F4-ED31-462B-8711-5BE508A4CD35}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{07F003F4-ED31-462B-8711-5BE508A4CD35}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{07F003F4-ED31-462B-8711-5BE508A4CD35}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{07F003F4-ED31-462B-8711-5BE508A4CD35}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -127,7 +127,7 @@ public class CrossLangFile
|
||||
|
||||
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.ico")))
|
||||
using (Stream strm = (Icon > -1 && Icon < Resources.Count) ? new MemoryStream(Resources[Icon], false) : AssetLoader.Open(new Uri("avares://CrossLangDevStudio/Assets/crosslang.png")))
|
||||
{
|
||||
return Bitmap.DecodeToHeight(strm, height);
|
||||
}
|
||||
@@ -210,7 +210,7 @@ public class CrossLangDependency
|
||||
{
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; } = "";
|
||||
[JsonProperty("verson")]
|
||||
[JsonProperty("version")]
|
||||
public CrossLangVersion Version { get; set; }
|
||||
|
||||
}
|
||||
|
||||
@@ -3,8 +3,10 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
@@ -14,6 +16,69 @@ namespace CrossLangDevStudio;
|
||||
|
||||
class CrossLangShell
|
||||
{
|
||||
public static string PackageServerFile = Path.Combine(CrossLangConfigDirectory, "package_servers.json");
|
||||
public static List<string> GetServers()
|
||||
{
|
||||
if (File.Exists(PackageServerFile))
|
||||
{
|
||||
var res = JsonConvert.DeserializeObject<List<string>>(File.ReadAllText(PackageServerFile));
|
||||
if (res is not null) return res;
|
||||
}
|
||||
return ["https://cpkg.tesseslanguage.com/"];
|
||||
}
|
||||
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"];
|
||||
private static void EscapeBashElement(StringBuilder builder, string val)
|
||||
{
|
||||
builder.Append("\"");
|
||||
foreach (var item in val)
|
||||
{
|
||||
switch (item)
|
||||
{
|
||||
case '$':
|
||||
case '`':
|
||||
case '\\':
|
||||
case '\"':
|
||||
case '!':
|
||||
builder.Append('\\');
|
||||
builder.Append(item);
|
||||
break;
|
||||
default:
|
||||
builder.Append(item);
|
||||
break;
|
||||
}
|
||||
}
|
||||
builder.Append("\"");
|
||||
}
|
||||
private static string EscapeBashCommand(string name, string[] args)
|
||||
{
|
||||
StringBuilder builder = new StringBuilder();
|
||||
EscapeBashElement(builder,name);
|
||||
foreach (var item in args)
|
||||
{
|
||||
builder.Append(' ');
|
||||
EscapeBashElement(builder,item);
|
||||
}
|
||||
builder.Append(" ; read -p \"Press Enter to close.\"");
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
private static string EscapeMacBashCommand(string workDir, bool keepOpen,string name, string[] args)
|
||||
{
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.Append("cd ");
|
||||
EscapeBashElement(builder, workDir);
|
||||
builder.Append(" ; ");
|
||||
EscapeBashElement(builder,name);
|
||||
foreach (var item in args)
|
||||
{
|
||||
builder.Append(' ');
|
||||
EscapeBashElement(builder,item);
|
||||
}
|
||||
if (keepOpen)
|
||||
builder.Append(" ; read -p \"Press Enter to close.\"");
|
||||
return builder.ToString();
|
||||
}
|
||||
private static CrossLangSettings? settings = null;
|
||||
public static CrossLangSettings Settings
|
||||
{
|
||||
@@ -88,7 +153,15 @@ class CrossLangShell
|
||||
}
|
||||
public static string GetRealPath(string exec)
|
||||
{
|
||||
foreach (var item in (Environment.GetEnvironmentVariable("PATH") ?? "").Split(Path.PathSeparator))
|
||||
var paths = (Environment.GetEnvironmentVariable("PATH") ?? "").Split(Path.PathSeparator).ToList();
|
||||
var execDir = Environment.ProcessPath;
|
||||
if (execDir is not null)
|
||||
{
|
||||
var dir = Path.GetDirectoryName(execDir);
|
||||
if(dir is not null)
|
||||
paths.Add(dir);
|
||||
}
|
||||
foreach (var item in paths)
|
||||
{
|
||||
var path = Path.Combine(item, exec);
|
||||
if (File.Exists(path)) return path;
|
||||
@@ -154,6 +227,10 @@ class CrossLangShell
|
||||
{
|
||||
string konsole = GetRealPath("konsole");
|
||||
string gnome_terminal = GetRealPath("gnome-terminal");
|
||||
string mate_terminal = GetRealPath("mate-terminal");
|
||||
string lxterminal = GetRealPath("lxterminal");
|
||||
string deepin_terminal = GetRealPath("deepin-terminal");
|
||||
string xfce_terminal = GetRealPath("xfce4-terminal");
|
||||
|
||||
string xterm = GetRealPath("xterm");
|
||||
if (File.Exists(konsole))
|
||||
@@ -175,28 +252,185 @@ class CrossLangShell
|
||||
}
|
||||
process.Start();
|
||||
}
|
||||
if (File.Exists(xfce_terminal))
|
||||
{
|
||||
using Process process = new Process();
|
||||
process.StartInfo.WorkingDirectory = workingDirectory;
|
||||
process.StartInfo.FileName = xfce_terminal;
|
||||
process.StartInfo.UseShellExecute = false;
|
||||
if (commandName.Length != 0)
|
||||
{
|
||||
if (keepOpen)
|
||||
process.StartInfo.ArgumentList.Add("--hold");
|
||||
process.StartInfo.ArgumentList.Add("-e");
|
||||
process.StartInfo.ArgumentList.Add(commandName);
|
||||
foreach (var arg in args)
|
||||
{
|
||||
process.StartInfo.ArgumentList.Add(arg);
|
||||
}
|
||||
}
|
||||
process.Start();
|
||||
}
|
||||
else if (File.Exists(gnome_terminal))
|
||||
{
|
||||
using Process process = new Process();
|
||||
process.StartInfo.WorkingDirectory = workingDirectory;
|
||||
process.StartInfo.FileName = gnome_terminal;
|
||||
process.StartInfo.UseShellExecute = false;
|
||||
if (commandName.Length != 0)
|
||||
{
|
||||
process.StartInfo.ArgumentList.Add("--");
|
||||
if (keepOpen)
|
||||
{
|
||||
process.StartInfo.ArgumentList.Add("bash");
|
||||
process.StartInfo.ArgumentList.Add("-c");
|
||||
process.StartInfo.ArgumentList.Add(EscapeBashCommand(commandName, args));
|
||||
}
|
||||
else
|
||||
{
|
||||
process.StartInfo.ArgumentList.Add(commandName);
|
||||
foreach (var arg in args)
|
||||
{
|
||||
process.StartInfo.ArgumentList.Add(arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
process.Start();
|
||||
}
|
||||
|
||||
else if (File.Exists(mate_terminal))
|
||||
{
|
||||
using Process process = new Process();
|
||||
process.StartInfo.WorkingDirectory = workingDirectory;
|
||||
process.StartInfo.FileName = mate_terminal;
|
||||
process.StartInfo.UseShellExecute = false;
|
||||
if (commandName.Length != 0)
|
||||
{
|
||||
process.StartInfo.ArgumentList.Add("--");
|
||||
if (keepOpen)
|
||||
{
|
||||
process.StartInfo.ArgumentList.Add("bash");
|
||||
process.StartInfo.ArgumentList.Add("-c");
|
||||
process.StartInfo.ArgumentList.Add(EscapeBashCommand(commandName, args));
|
||||
}
|
||||
else
|
||||
{
|
||||
process.StartInfo.ArgumentList.Add(commandName);
|
||||
foreach (var arg in args)
|
||||
{
|
||||
process.StartInfo.ArgumentList.Add(arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
process.Start();
|
||||
}
|
||||
else if (File.Exists(lxterminal))
|
||||
{
|
||||
using Process process = new Process();
|
||||
process.StartInfo.WorkingDirectory = workingDirectory;
|
||||
process.StartInfo.FileName = lxterminal;
|
||||
process.StartInfo.UseShellExecute = false;
|
||||
if (commandName.Length != 0)
|
||||
{
|
||||
process.StartInfo.ArgumentList.Add("-e");
|
||||
if (keepOpen)
|
||||
{
|
||||
process.StartInfo.ArgumentList.Add("bash");
|
||||
process.StartInfo.ArgumentList.Add("-c");
|
||||
process.StartInfo.ArgumentList.Add(EscapeBashCommand(commandName, args));
|
||||
}
|
||||
else
|
||||
{
|
||||
process.StartInfo.ArgumentList.Add(commandName);
|
||||
foreach (var arg in args)
|
||||
{
|
||||
process.StartInfo.ArgumentList.Add(arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
process.Start();
|
||||
}
|
||||
|
||||
else if (File.Exists(deepin_terminal))
|
||||
{
|
||||
using Process process = new Process();
|
||||
process.StartInfo.WorkingDirectory = workingDirectory;
|
||||
process.StartInfo.FileName = deepin_terminal;
|
||||
process.StartInfo.UseShellExecute = false;
|
||||
if (commandName.Length != 0)
|
||||
{
|
||||
if (keepOpen)
|
||||
process.StartInfo.ArgumentList.Add("--keep-open");
|
||||
process.StartInfo.ArgumentList.Add("-e");
|
||||
process.StartInfo.ArgumentList.Add(commandName);
|
||||
foreach (var arg in args)
|
||||
{
|
||||
process.StartInfo.ArgumentList.Add(arg);
|
||||
}
|
||||
}
|
||||
process.Start();
|
||||
}
|
||||
else if (File.Exists(xterm))
|
||||
{
|
||||
|
||||
using Process process = new Process();
|
||||
process.StartInfo.WorkingDirectory = workingDirectory;
|
||||
process.StartInfo.FileName = xterm;
|
||||
process.StartInfo.UseShellExecute = false;
|
||||
if (commandName.Length != 0)
|
||||
{
|
||||
if (keepOpen)
|
||||
process.StartInfo.ArgumentList.Add("-hold");
|
||||
process.StartInfo.ArgumentList.Add("-e");
|
||||
process.StartInfo.ArgumentList.Add(commandName);
|
||||
foreach (var arg in args)
|
||||
{
|
||||
process.StartInfo.ArgumentList.Add(arg);
|
||||
}
|
||||
}
|
||||
process.Start();
|
||||
}
|
||||
}
|
||||
else if (OperatingSystem.IsWindows())
|
||||
{
|
||||
using Process process = new Process();
|
||||
process.StartInfo.FileName = GetRealPath("cmd.exe");
|
||||
if(commandName.Length > 0)
|
||||
process.StartInfo.ArgumentList.Add(keepOpen ? "/K" : "/C");
|
||||
if (commandName.Length > 0)
|
||||
process.StartInfo.ArgumentList.Add(keepOpen ? "/K" : "/C");
|
||||
process.StartInfo.CreateNoWindow = false;
|
||||
process.StartInfo.UseShellExecute = false;
|
||||
process.StartInfo.WorkingDirectory = workingDirectory;
|
||||
if(commandName.Length > 0)
|
||||
process.StartInfo.ArgumentList.Add(commandName);
|
||||
foreach (var item in args)
|
||||
process.StartInfo.ArgumentList.Add(item);
|
||||
if (commandName.Length > 0)
|
||||
process.StartInfo.ArgumentList.Add(commandName);
|
||||
if (commandName.Length > 0)
|
||||
foreach (var item in args)
|
||||
process.StartInfo.ArgumentList.Add(item);
|
||||
process.Start();
|
||||
}
|
||||
else if (OperatingSystem.IsMacOS())
|
||||
{
|
||||
using Process process = new Process();
|
||||
process.StartInfo.WorkingDirectory = workingDirectory;
|
||||
process.StartInfo.FileName = GetRealPath("open");
|
||||
process.StartInfo.UseShellExecute = false;
|
||||
if (commandName.Length != 0)
|
||||
{
|
||||
process.StartInfo.ArgumentList.Add("-b");
|
||||
process.StartInfo.ArgumentList.Add("com.apple.terminal");
|
||||
if (keepOpen)
|
||||
{
|
||||
process.StartInfo.ArgumentList.Add("bash");
|
||||
process.StartInfo.ArgumentList.Add("-c");
|
||||
process.StartInfo.ArgumentList.Add(EscapeMacBashCommand(workingDirectory, keepOpen, commandName, args));
|
||||
}
|
||||
else
|
||||
{
|
||||
process.StartInfo.ArgumentList.Add(commandName);
|
||||
foreach (var arg in args)
|
||||
{
|
||||
process.StartInfo.ArgumentList.Add(arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
process.Start();
|
||||
}
|
||||
}
|
||||
|
||||
12
Messages/InstallPackageMessage.cs
Normal file
12
Messages/InstallPackageMessage.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using CrossLangDevStudio.ViewModels;
|
||||
using CommunityToolkit.Mvvm.Messaging.Messages;
|
||||
using System.Net.Http;
|
||||
|
||||
namespace CrossLangDevStudio.Messages;
|
||||
|
||||
public class InstallPackageMessage(HttpClient client,string name, string server) : AsyncRequestMessage<CrossLangVersion?>
|
||||
{
|
||||
public HttpClient Client => client;
|
||||
public string Name => name;
|
||||
public string Server => server;
|
||||
}
|
||||
9
Messages/InstallPackageResponseMessage.cs
Normal file
9
Messages/InstallPackageResponseMessage.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
using CrossLangDevStudio.ViewModels;
|
||||
using CommunityToolkit.Mvvm.Messaging.Messages;
|
||||
|
||||
namespace CrossLangDevStudio.Messages;
|
||||
|
||||
public class InstallPackageResponseMessage(CrossLangVersion? version) : AsyncRequestMessage<CrossLangVersion?>
|
||||
{
|
||||
public CrossLangVersion? Version => version;
|
||||
}
|
||||
42
Models/IPackageManager.cs
Normal file
42
Models/IPackageManager.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Threading.Tasks;
|
||||
using Avalonia.Controls;
|
||||
|
||||
namespace CrossLangDevStudio.Models;
|
||||
|
||||
public interface IPackageManager
|
||||
{
|
||||
Task InstallPackageAsync(string name, CrossLangVersion version);
|
||||
string Filter { get; }
|
||||
void UninstallPackage(string name);
|
||||
|
||||
IEnumerable<CrossLangDependency> GetInstalledPackages();
|
||||
}
|
||||
|
||||
public static class PackageManagerExtensions
|
||||
{
|
||||
public static string Summarize(this string txt)
|
||||
{
|
||||
var lines = txt.Replace("\r", "").Split('\n');
|
||||
bool needsthreedots = false;
|
||||
if (lines.Length > 1) needsthreedots = true;
|
||||
if (lines.Length == 0) return "";
|
||||
if (lines[0].Length > 120) { needsthreedots = true; lines[0] = lines[0].Substring(0, 120); }
|
||||
if (needsthreedots) return $"{lines[0]}...";
|
||||
return lines[0];
|
||||
}
|
||||
public static bool IsPackageInstalled(this IPackageManager pm, string name)
|
||||
{
|
||||
foreach (var item in pm.GetInstalledPackages())
|
||||
{
|
||||
if (item.Name == name) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public static async Task InstallPackageAsync(this IPackageManager pm, CrossLangDependency dep)
|
||||
{
|
||||
await pm.InstallPackageAsync(dep.Name, dep.Version);
|
||||
}
|
||||
}
|
||||
70
Models/ProjectPackageManager.cs
Normal file
70
Models/ProjectPackageManager.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;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace CrossLangDevStudio.Models;
|
||||
|
||||
public class ProjectPackageManager : IPackageManager
|
||||
{
|
||||
public ProjectPackageManager(string path)
|
||||
{
|
||||
Path = path;
|
||||
}
|
||||
public string Path { get; init; }
|
||||
public string Filter => "lib,compile_tool";
|
||||
|
||||
public IEnumerable<CrossLangDependency> GetInstalledPackages()
|
||||
{
|
||||
var cfg = JsonConvert.DeserializeObject<CrossLangConfig>(File.ReadAllText(Path));
|
||||
if (cfg is not null)
|
||||
{
|
||||
foreach (var item in cfg.Dependencies)
|
||||
{
|
||||
yield return item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async Task InstallPackageAsync(string name, CrossLangVersion version)
|
||||
{
|
||||
var cfg = JsonConvert.DeserializeObject<CrossLangConfig>(await File.ReadAllTextAsync(Path)) ?? new CrossLangConfig();
|
||||
cfg.Dependencies ??= new List<CrossLangDependency>();
|
||||
bool has = false;
|
||||
foreach (var item in cfg.Dependencies)
|
||||
{
|
||||
if (item.Name == name)
|
||||
{
|
||||
has = true;
|
||||
if(version.CompareTo(item.Version) > 0)
|
||||
item.Version = version;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!has) cfg.Dependencies.Add(new CrossLangDependency { Name = name, Version = version });
|
||||
await File.WriteAllTextAsync(Path, JsonConvert.SerializeObject(cfg, Formatting.Indented, new JsonSerializerSettings(){NullValueHandling= NullValueHandling.Ignore}));
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void UninstallPackage(string name)
|
||||
{
|
||||
var cfg = JsonConvert.DeserializeObject<CrossLangConfig>(File.ReadAllText(Path)) ?? new CrossLangConfig();
|
||||
cfg.Dependencies ??= new List<CrossLangDependency>();
|
||||
|
||||
foreach (var item in cfg.Dependencies)
|
||||
{
|
||||
if (item.Name == name)
|
||||
{
|
||||
cfg.Dependencies.Remove(item);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
File.WriteAllText(Path, JsonConvert.SerializeObject(cfg, Formatting.Indented,new JsonSerializerSettings(){NullValueHandling= NullValueHandling.Ignore}));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
#!/bin/bash
|
||||
mkdir build
|
||||
cd build
|
||||
mkdir crosslang-devstudio_1.0.0_amd64
|
||||
cd crosslang-devstudio_1.0.0_amd64
|
||||
dotnet publish -c Release -r linux-x64 -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-amd64 DEBIAN/control
|
||||
cp ../../crosslang-devstudio.desktop usr/share/applications/
|
||||
cp ../../crossdev usr/bin/crossdev
|
||||
chmod 755 usr/bin/crossdev
|
||||
cd ..
|
||||
dpkg-deb --build crosslang-devstudio_1.0.0_amd64/
|
||||
|
||||
2
Packaging/Linux/crossdev
Normal file
2
Packaging/Linux/crossdev
Normal file
@@ -0,0 +1,2 @@
|
||||
#!/bin/bash
|
||||
/opt/CrossLangDevStudio/CrossLangDevStudio "$@"
|
||||
8
Packaging/Linux/crosslang-devstudio.desktop
Normal file
8
Packaging/Linux/crosslang-devstudio.desktop
Normal file
@@ -0,0 +1,8 @@
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Version=1.0
|
||||
Name=CrossLang DevStudio
|
||||
Exec=crossdev
|
||||
Icon=crosslang
|
||||
Categories=Education;Languages;Programming
|
||||
Comment=IDE For CrossLang
|
||||
8
Packaging/Linux/debian/control-amd64
Normal file
8
Packaging/Linux/debian/control-amd64
Normal file
@@ -0,0 +1,8 @@
|
||||
Package: crosslang-devstudio
|
||||
Version: 1.0.0
|
||||
Architecture: amd64
|
||||
Essential: no
|
||||
Priority: optional
|
||||
Depends: crosslang
|
||||
Maintainer: Mike Nolan
|
||||
Description: IDE for CrossLang
|
||||
6
Packaging/Linux/push.sh
Normal file
6
Packaging/Linux/push.sh
Normal file
@@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
curl --user tesses50:$GITEA_AUTH -X DELETE \
|
||||
https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/jammy/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/jammy/main/upload
|
||||
@@ -5,7 +5,7 @@ git clone https://onedev.site.tesses.net/crosslang
|
||||
cd crosslang
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -S .. -B . -DCMAKE_TOOLCHAIN_FILE=../../../Toolchain.cmake -DTESSESFRAMEWORK_ENABLE_SHARED=OFF -DTESSESFRAMEWORK_FETCHCONTENT=ON
|
||||
cmake -S .. -B . -DCMAKE_TOOLCHAIN_FILE=../../../Toolchain.cmake -DTESSESFRAMEWORK_ENABLE_SHARED=OFF -DTESSESFRAMEWORK_ENABLE_STATIC=ON -DTESSESFRAMEWORK_ENABLE_APPS=OFF -DTESSESFRAMEWORK_ENABLE_EXAMPLES=OFF -DTESSESFRAMEWORK_FETCHCONTENT=ON
|
||||
make -j`nproc`
|
||||
mkdir -p ../../package/bin
|
||||
mkdir -p ../../package/share/Tesses/CrossLang
|
||||
|
||||
88
ViewModels/InstallPackageDialogViewModel.cs
Normal file
88
ViewModels/InstallPackageDialogViewModel.cs
Normal file
@@ -0,0 +1,88 @@
|
||||
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;
|
||||
|
||||
namespace CrossLangDevStudio.ViewModels;
|
||||
|
||||
public partial class InstallPackageDialogViewModel : ViewModelBase
|
||||
{
|
||||
public InstallPackageMessage Message { get; }
|
||||
[ObservableProperty]
|
||||
private int _versionIndex = 0;
|
||||
public ObservableCollection<VersionObject> Versions { get; } = new ObservableCollection<VersionObject>();
|
||||
|
||||
public InstallPackageDialogViewModel(InstallPackageMessage msg)
|
||||
{
|
||||
Message = msg;
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
var res = await Message.Client.GetStringAsync($"{msg.Server.TrimEnd('/')}/api/v1/versions?name={HttpUtility.UrlEncode(msg.Name)}");
|
||||
if (!string.IsNullOrWhiteSpace(res))
|
||||
{
|
||||
var res2 = JsonConvert.DeserializeObject<VersionsMessage>(res);
|
||||
if (res2 is not null && res2.Success)
|
||||
{
|
||||
foreach (var res3 in res2.Versions)
|
||||
{
|
||||
Versions.Add(res3.ToObject());
|
||||
}
|
||||
VersionIndex = 0;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
[RelayCommand]
|
||||
private void Install()
|
||||
{
|
||||
if(VersionIndex < Versions.Count)
|
||||
WeakReferenceMessenger.Default.Send(new InstallPackageResponseMessage(Versions[VersionIndex].Version));
|
||||
}
|
||||
[RelayCommand]
|
||||
private void Cancel()
|
||||
{
|
||||
WeakReferenceMessenger.Default.Send(new InstallPackageResponseMessage(null));
|
||||
}
|
||||
public partial class VersionObject(CrossLangVersion version, DateTime date) : ObservableObject
|
||||
{
|
||||
public CrossLangVersion Version => version;
|
||||
[ObservableProperty]
|
||||
private string _text = $"{version} at {date.ToShortDateString()}";
|
||||
}
|
||||
|
||||
public class VersionsMessage
|
||||
{
|
||||
[JsonProperty("success")]
|
||||
public bool Success { get; set; }
|
||||
[JsonProperty("versions")]
|
||||
public List<VersionMessage> Versions { get; set; } = new();
|
||||
|
||||
public class VersionMessage
|
||||
{
|
||||
[JsonProperty("version")]
|
||||
public CrossLangVersion Version { get; set; }
|
||||
|
||||
[JsonProperty("uploadTime")]
|
||||
public long UploadTime { get; set; } = 0;
|
||||
|
||||
public VersionObject ToObject()
|
||||
{
|
||||
|
||||
return new VersionObject(Version, DateTimeOffset.FromUnixTimeSeconds(UploadTime).LocalDateTime);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -122,7 +122,12 @@ public partial class MainWindowViewModel : ViewModelBase
|
||||
|
||||
OpenProjectConfig();
|
||||
}),
|
||||
new ProjectFileNode("Packages")
|
||||
new ProjectFileNode("Packages", ()=>{
|
||||
OpenProjectPackages();
|
||||
}),
|
||||
new ProjectFileNode("Project Dependencies",()=>{
|
||||
|
||||
})
|
||||
])
|
||||
|
||||
};
|
||||
@@ -151,6 +156,33 @@ public partial class MainWindowViewModel : ViewModelBase
|
||||
ProjectFiles.Add(new ProjectFileNode(Path.GetFileName(obj), entries));
|
||||
}
|
||||
|
||||
private void OpenProjectPackages()
|
||||
{
|
||||
if (Directory.Exists(CurrentProject))
|
||||
{
|
||||
var config = Path.Combine(CurrentProject, "cross.json");
|
||||
if (File.Exists(config))
|
||||
{
|
||||
foreach (var item in TabItems)
|
||||
{
|
||||
if (item.Body is PackageManagerViewModel vm)
|
||||
{
|
||||
if (vm.Packages is ProjectPackageManager)
|
||||
{
|
||||
SelectedTab = item;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
AddTab(new TabItemViewModel()
|
||||
{
|
||||
Header = "Project Packages",
|
||||
Body = new PackageManagerViewModel(this, new ProjectPackageManager(config))
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OpenProjectConfig()
|
||||
{
|
||||
|
||||
@@ -161,6 +193,7 @@ public partial class MainWindowViewModel : ViewModelBase
|
||||
{
|
||||
if (item.Body is ProjectConfigurationViewModel model && model.FilePath == config)
|
||||
{
|
||||
SelectedTab = item;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ public partial class NewProjectDialogViewModel : ViewModelBase
|
||||
int i;
|
||||
for (i = 1; i < int.MaxValue; i++)
|
||||
{
|
||||
string name2 = $"{name}{i}";
|
||||
string name2 = $"{newName}{i}";
|
||||
if (!Directory.Exists(Path.Combine(ParentDirectory, name2)))
|
||||
{
|
||||
Name = name2;
|
||||
|
||||
203
ViewModels/PackageManagerViewModel.cs
Normal file
203
ViewModels/PackageManagerViewModel.cs
Normal file
@@ -0,0 +1,203 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
using Avalonia;
|
||||
using Avalonia.Animation;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Media.Imaging;
|
||||
using Avalonia.Platform.Storage;
|
||||
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using CrossLangDevStudio.Messages;
|
||||
using CrossLangDevStudio.Models;
|
||||
using CrossLangDevStudio.Views;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace CrossLangDevStudio.ViewModels;
|
||||
|
||||
|
||||
public partial class PackageManagerViewModel : ViewModelBase
|
||||
{
|
||||
public IPackageManager Packages { get; }
|
||||
|
||||
public ObservableCollection<Package> PackageList { get; } = new ObservableCollection<Package>();
|
||||
|
||||
public ObservableCollection<string> Servers { get; } = new ObservableCollection<string>();
|
||||
|
||||
[ObservableProperty]
|
||||
private int _serverIndex = 0;
|
||||
|
||||
[ObservableProperty]
|
||||
private string _search = "";
|
||||
|
||||
[ObservableProperty]
|
||||
private int _page = 1;
|
||||
|
||||
public MainWindowViewModel Main { get; }
|
||||
|
||||
|
||||
public PackageManagerViewModel(MainWindowViewModel mvm, IPackageManager pm)
|
||||
{
|
||||
Main = mvm;
|
||||
Packages = pm;
|
||||
foreach(var svr in CrossLangShell.GetServers())
|
||||
this.Servers.Add(svr);
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private async Task SearchPackagesAsync()
|
||||
{
|
||||
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 res = JsonConvert.DeserializeObject<SearchResult>(body);
|
||||
PackageList.Clear();
|
||||
if (res is not null)
|
||||
{
|
||||
|
||||
foreach (var item in res.Packages)
|
||||
{
|
||||
Package pkg = new Package();
|
||||
var date = DateTimeOffset.FromUnixTimeSeconds(item.UploadTime);
|
||||
var date2 = date.ToLocalTime().DateTime;
|
||||
|
||||
pkg.Info = $"Version: {item.Version}\tAccount: {item.AccountName}\tUpdated: {date2.ToShortDateString()}\tLicense: {item.License}\tType: {item.Type}";
|
||||
|
||||
pkg.Version = item.Version;
|
||||
pkg.Name = item.Name;
|
||||
pkg.Description = item.Description.Summarize();
|
||||
pkg.IsInstalled = Packages.IsPackageInstalled(item.Name);
|
||||
pkg.Install = async() =>
|
||||
{
|
||||
var resp = await WeakReferenceMessenger.Default.Send(new InstallPackageMessage(Main.Client, item.Name, svr));
|
||||
if (resp.HasValue)
|
||||
{
|
||||
await Packages.InstallPackageAsync(item.Name, resp.Value);
|
||||
pkg.IsInstalled = true;
|
||||
}
|
||||
};
|
||||
pkg.Uninstall = () =>
|
||||
{
|
||||
Packages.UninstallPackage(item.Name);
|
||||
pkg.IsInstalled = false;
|
||||
};
|
||||
|
||||
|
||||
byte[] data = await Main.Client.GetByteArrayAsync($"{svr}/api/v1/package_icon.png?name={HttpUtility.UrlEncode(item.Name)}&version={item.Version.ToString()}");
|
||||
using var ms = new MemoryStream(data, false);
|
||||
pkg.Icon = Bitmap.DecodeToHeight(ms, 64);
|
||||
PackageList.Add(pkg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class SearchPackage
|
||||
{
|
||||
[JsonProperty("packageName")]
|
||||
public string Name { get; set; } = "";
|
||||
|
||||
[JsonProperty("version")]
|
||||
public CrossLangVersion Version { get; set; }
|
||||
|
||||
[JsonProperty("uploadTime")]
|
||||
public long UploadTime { get; set; }
|
||||
|
||||
[JsonProperty("license")]
|
||||
public string License { get; set; } = "";
|
||||
|
||||
[JsonProperty("type")]
|
||||
public string Type { get; set; } = "";
|
||||
[JsonProperty("accountName")]
|
||||
public string AccountName { get; set; } = "";
|
||||
[JsonProperty("description")]
|
||||
public string Description { get; set; } = "";
|
||||
}
|
||||
|
||||
public partial class Package : ObservableObject
|
||||
{
|
||||
[ObservableProperty]
|
||||
private string _name = "";
|
||||
|
||||
public CrossLangVersion Version { get; set; }
|
||||
public Func<Task>? Install { get; set; }
|
||||
public Func<Task>? GetInfo { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
private string _info = "";
|
||||
[ObservableProperty]
|
||||
private string _description = "";
|
||||
|
||||
[ObservableProperty]
|
||||
private IImage? _icon = null;
|
||||
|
||||
[ObservableProperty]
|
||||
private string _mainButtonText = "";
|
||||
|
||||
[ObservableProperty]
|
||||
private string _subButton1Text = "";
|
||||
private bool _isInstalled = false;
|
||||
public bool IsInstalled
|
||||
{
|
||||
get => _isInstalled;
|
||||
set
|
||||
{
|
||||
SetProperty(ref _isInstalled, value, nameof(IsInstalled));
|
||||
|
||||
MainButtonText = value ? "Uninstall" : "Install";
|
||||
SubButton1Text = value ? "Change Version" : "Info";
|
||||
}
|
||||
}
|
||||
|
||||
public Action? Uninstall { get; set; }
|
||||
|
||||
[RelayCommand]
|
||||
private async Task MainButtonAsync()
|
||||
{
|
||||
/*var i = Install;
|
||||
if (i is not null) await i();*/
|
||||
|
||||
if (_isInstalled)
|
||||
{
|
||||
Uninstall?.Invoke();
|
||||
}
|
||||
else
|
||||
{
|
||||
var i = Install;
|
||||
if (i is not null) await i();
|
||||
}
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private async Task SubButton1Async()
|
||||
{
|
||||
if (_isInstalled)
|
||||
{
|
||||
var i = Install;
|
||||
if (i is not null) await i();
|
||||
}
|
||||
else
|
||||
{
|
||||
var i = GetInfo;
|
||||
if (i is not null) await i();
|
||||
}
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private async Task SubButton2Async()
|
||||
{
|
||||
var i = GetInfo;
|
||||
if (i is not null) await i();
|
||||
}
|
||||
}
|
||||
|
||||
public class SearchResult
|
||||
{
|
||||
[JsonProperty("packages")]
|
||||
public List<SearchPackage> Packages { get; set; } = new List<SearchPackage>();
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,6 @@ public partial class ProjectConfigurationViewModel : ViewModelBase, ISavable
|
||||
<ComboBoxItem>Tool</ComboBoxItem>
|
||||
<ComboBoxItem>Archive</ComboBoxItem>
|
||||
*/
|
||||
static readonly string[] types = ["console","lib","app","template","compile_tool","tool","archive"];
|
||||
TabItemViewModel tab;
|
||||
public string FilePath { get; }
|
||||
bool _modified = false;
|
||||
@@ -186,7 +185,7 @@ public partial class ProjectConfigurationViewModel : ViewModelBase, ISavable
|
||||
_license = config?.Info?.License ?? "";
|
||||
_templatename = config?.Info?.TemplateName ?? "";
|
||||
_templatenamepretty = config?.Info?.TemplateNamePretty ?? "";
|
||||
_type = Array.IndexOf(types, config?.Info?.Type ?? "console");
|
||||
_type = Array.IndexOf(CrossLangShell.ProjectTypes, config?.Info?.Type ?? "console");
|
||||
_type = _type == -1 ? 0 : _type;
|
||||
_description = config?.Info?.Description ?? "";
|
||||
|
||||
@@ -210,7 +209,7 @@ public partial class ProjectConfigurationViewModel : ViewModelBase, ISavable
|
||||
config.Info.Repoository = string.IsNullOrWhiteSpace(Repository) ? null : Repository;
|
||||
config.Info.TemplateName = string.IsNullOrWhiteSpace(TemplateName) ? null : TemplateName;
|
||||
config.Info.TemplateNamePretty = string.IsNullOrWhiteSpace(TemplateNamePretty) ? null : TemplateNamePretty;
|
||||
config.Info.Type = types[Type];
|
||||
config.Info.Type = CrossLangShell.ProjectTypes[Type];
|
||||
File.WriteAllText(FilePath, JsonConvert.SerializeObject(config, Formatting.Indented, new JsonSerializerSettings()
|
||||
{
|
||||
NullValueHandling = NullValueHandling.Ignore
|
||||
|
||||
46
Views/InstallPackageDialog.axaml
Normal file
46
Views/InstallPackageDialog.axaml
Normal file
@@ -0,0 +1,46 @@
|
||||
<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="320"
|
||||
Height="120"
|
||||
WindowStartupLocation="CenterOwner"
|
||||
x:Class="CrossLangDevStudio.Views.InstallPackageDialog"
|
||||
x:DataType="vm:InstallPackageDialogViewModel"
|
||||
Icon="/Assets/crosslang.ico"
|
||||
Title="Install Package">
|
||||
<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:InstallPackageDialogViewModel/>
|
||||
</Design.DataContext>
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*"/>
|
||||
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
<ComboBox Grid.Row="1" ItemsSource="{Binding Versions}" HorizontalAlignment="Stretch" SelectedIndex="{Binding VersionIndex}">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Text}"/>
|
||||
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
<Grid Grid.Row="3">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Button Content="Install" Grid.Column="1" Command="{Binding InstallCommand}" />
|
||||
<Button Content="Cancel" Grid.Column="2" Command="{Binding CancelCommand}" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Window>
|
||||
21
Views/InstallPackageDialog.axaml.cs
Normal file
21
Views/InstallPackageDialog.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 InstallPackageDialog : Window
|
||||
{
|
||||
public InstallPackageDialog()
|
||||
{
|
||||
InitializeComponent();
|
||||
if (Design.IsDesignMode) return;
|
||||
|
||||
WeakReferenceMessenger.Default.Register<InstallPackageDialog, InstallPackageResponseMessage>(this, static (w, m) =>
|
||||
{
|
||||
w.Close(m.Version);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,7 @@
|
||||
<MenuItem Header="_Open Project" HotKey="Ctrl+O" Command="{Binding OpenProjectCommand}"/>
|
||||
<MenuItem Header="_Save" HotKey="Ctrl+S" Command="{Binding SaveCommand}"/>
|
||||
<MenuItem Header="Save All" HotKey="Ctrl+Shift+S" Command="{Binding SaveAllCommand}"/>
|
||||
<MenuItem Header="CrossLang Settings"/>
|
||||
<Separator/>
|
||||
<MenuItem Header="_Exit" HotKey="Alt+F4"/>
|
||||
</MenuItem>
|
||||
@@ -38,6 +39,23 @@
|
||||
<MenuItem Header="Open In Terminal" HotKey="CTRL+T" Command="{Binding OpenProjectInTerminalCommand}" />
|
||||
<MenuItem Header="Refresh" HotKey="CTRL+R" Command="{Binding RefreshListingCommand}" />
|
||||
</MenuItem>
|
||||
<MenuItem Header="_CPKG">
|
||||
<MenuItem Header="Add Package"/>
|
||||
<MenuItem Header="Install">
|
||||
<MenuItem Header="Template"/>
|
||||
<MenuItem Header="Tool"/>
|
||||
<MenuItem Header="Web Application"/>
|
||||
<MenuItem Header="Console Application"/>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Push Package"/>
|
||||
<MenuItem Header="Manage Servers"/>
|
||||
</MenuItem>
|
||||
<MenuItem Header="_Help">
|
||||
|
||||
<MenuItem Header="Welcome"/>
|
||||
<MenuItem Header="Website"/>
|
||||
<MenuItem Header="Documentation"/>
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
<Grid Grid.Row="1" ColumnDefinitions="300, 4, *">
|
||||
<TreeView Grid.Column="0" ItemsSource="{Binding ProjectFiles}" SelectedItem="{Binding SelectedProjectFile}">
|
||||
|
||||
@@ -28,6 +28,15 @@ public partial class MainWindow : Window
|
||||
// Show dialog window and reply with returned AlbumViewModel or null when the dialog is closed.
|
||||
m.Reply(dialog.ShowDialog<string?>(w));
|
||||
});
|
||||
WeakReferenceMessenger.Default.Register<MainWindow, InstallPackageMessage>(this, static (w, m) =>
|
||||
{
|
||||
var dialog = new InstallPackageDialog
|
||||
{
|
||||
DataContext = new InstallPackageDialogViewModel(m)
|
||||
};
|
||||
|
||||
m.Reply(dialog.ShowDialog<CrossLangVersion?>(w));
|
||||
});
|
||||
WeakReferenceMessenger.Default.Register<MainWindow, GetWindowMessage>(this, static (w, m) =>
|
||||
{
|
||||
m.Reply(w);
|
||||
|
||||
76
Views/PackageManagerView.axaml
Normal file
76
Views/PackageManagerView.axaml
Normal file
@@ -0,0 +1,76 @@
|
||||
<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.PackageManagerView"
|
||||
x:DataType="vm:PackageManagerViewModel">
|
||||
<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:PackageManagerViewModel />
|
||||
</Design.DataContext>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Grid Grid.Row="0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBox Grid.Column="0" Text="{Binding Search}" Watermark="Search..." />
|
||||
<ComboBox Grid.Column="1" ItemsSource="{Binding Servers}" SelectedIndex="{Binding ServerIndex}" />
|
||||
<Button Grid.Column="2" Content="Search" Command="{Binding SearchPackagesCommand}" />
|
||||
</Grid>
|
||||
<ScrollViewer Grid.Row="1" HorizontalScrollBarVisibility="Auto">
|
||||
<ItemsControl ItemsSource="{Binding PackageList}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="64" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Image Grid.Column="0" Source="{Binding Icon}" />
|
||||
<Grid Grid.Column="1">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock Grid.Row="0" Text="{Binding Name}"/>
|
||||
<TextBlock Grid.Row="1" Text="{Binding Info}"/>
|
||||
<TextBlock Grid.Row="2" Text="{Binding Description}"/>
|
||||
</Grid>
|
||||
<Grid Grid.Column="2">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<SplitButton Grid.Row="0" Content="{Binding MainButtonText}" Command="{Binding MainButtonCommand}">
|
||||
<SplitButton.Flyout>
|
||||
<MenuFlyout Placement="Bottom">
|
||||
<MenuItem Header="{Binding SubButton1Text}" Command="{Binding SubButton1Command}" />
|
||||
<MenuItem Header="Info" IsVisible="{Binding IsInstalled}" Command="{Binding SubButton2Command}" />
|
||||
</MenuFlyout>
|
||||
</SplitButton.Flyout>
|
||||
</SplitButton>
|
||||
|
||||
|
||||
</Grid>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
|
||||
</UserControl>
|
||||
11
Views/PackageManagerView.axaml.cs
Normal file
11
Views/PackageManagerView.axaml.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using Avalonia.Controls;
|
||||
|
||||
namespace CrossLangDevStudio.Views;
|
||||
|
||||
public partial class PackageManagerView : UserControl
|
||||
{
|
||||
public PackageManagerView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user