run panel tabs

This commit is contained in:
Matt Parker
2025-08-25 18:42:46 +10:00
parent 8826c31a63
commit feffc0d7a8
17 changed files with 163 additions and 30 deletions

View File

@@ -34,7 +34,7 @@ public class DebuggingService
var debugProtocolHost = new DebugProtocolHost(process.StandardInput.BaseStream, process.StandardOutput.BaseStream, false);
debugProtocolHost.LogMessage += (sender, args) =>
{
Console.WriteLine($"Log message: {args.Message}");
//Console.WriteLine($"Log message: {args.Message}");
};
debugProtocolHost.EventReceived += (sender, args) =>
{

View File

@@ -1,4 +1,6 @@
namespace SharpIDE.Application.Features.Events;
using SharpIDE.Application.Features.SolutionDiscovery.VsPersistence;
namespace SharpIDE.Application.Features.Events;
public static class GlobalEvents
{
@@ -7,4 +9,10 @@ public static class GlobalEvents
public static event Func<Task> StartedRunningProject = () => Task.CompletedTask;
public static void InvokeStartedRunningProject() => StartedRunningProject?.Invoke();
public static event Func<SharpIdeProjectModel, Task> ProjectStartedRunning = _ => Task.CompletedTask;
public static void InvokeProjectStartedRunning(SharpIdeProjectModel project) => ProjectStartedRunning?.Invoke(project);
public static event Func<SharpIdeProjectModel, Task> ProjectStoppedRunning = _ => Task.CompletedTask;
public static void InvokeProjectStoppedRunning(SharpIdeProjectModel project) => ProjectStoppedRunning?.Invoke(project);
}

View File

@@ -89,6 +89,7 @@ public class RunService
project.OpenInRunPanel = true;
GlobalEvents.InvokeProjectsRunningChanged();
GlobalEvents.InvokeStartedRunningProject();
GlobalEvents.InvokeProjectStartedRunning(project);
project.InvokeProjectStartedRunning();
await process.WaitForExitAsync().WaitAsync(project.RunningCancellationTokenSource.Token).ConfigureAwait(ConfigureAwaitOptions.SuppressThrowing);
if (project.RunningCancellationTokenSource.IsCancellationRequested)
@@ -118,6 +119,7 @@ public class RunService
if (project.RunningCancellationTokenSource is null) throw new InvalidOperationException($"Project {project.Name} does not have a running cancellation token source.");
await project.RunningCancellationTokenSource.CancelAsync().ConfigureAwait(false);
GlobalEvents.InvokeProjectStoppedRunning(project);
}
private string GetRunArguments(SharpIdeProjectModel project)

View File

Before

Width:  |  Height:  |  Size: 291 B

After

Width:  |  Height:  |  Size: 291 B

View File

@@ -3,15 +3,15 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://bnprs1lvjyaji"
path="res://.godot/imported/Play.png-f33bbb4899ca2148d51910992d85a9eb.ctex"
path="res://.godot/imported/Play.png-3438a21a8b920e7517d04626c592e8b6.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Features/Run/Play.png"
dest_files=["res://.godot/imported/Play.png-f33bbb4899ca2148d51910992d85a9eb.ctex"]
source_file="res://Features/Run/Resources/Play.png"
dest_files=["res://.godot/imported/Play.png-3438a21a8b920e7517d04626c592e8b6.ctex"]
[params]

Binary file not shown.

After

Width:  |  Height:  |  Size: 743 B

View File

@@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://76nkes2imlf2"
path="res://.godot/imported/Running.png-d687d5fa2c32934f935f7cb594c7886d.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Features/Run/Resources/Running.png"
dest_files=["res://.godot/imported/Running.png-d687d5fa2c32934f935f7cb594c7886d.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View File

Before

Width:  |  Height:  |  Size: 607 B

After

Width:  |  Height:  |  Size: 607 B

View File

@@ -3,15 +3,15 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://csj1r7s3u10ch"
path="res://.godot/imported/Stop.png-369cb830460ee73ee5ab96abbb3f5c92.ctex"
path="res://.godot/imported/Stop.png-57d1375a399a106e4fdece5825762ac9.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://Features/Run/Stop.png"
dest_files=["res://.godot/imported/Stop.png-369cb830460ee73ee5ab96abbb3f5c92.ctex"]
source_file="res://Features/Run/Resources/Stop.png"
dest_files=["res://.godot/imported/Stop.png-57d1375a399a106e4fdece5825762ac9.ctex"]
[params]

View File

@@ -1,8 +1,8 @@
[gd_scene load_steps=4 format=3 uid="uid://d2ewm2lajutpv"]
[ext_resource type="Script" uid="uid://btsnapfx0dlbb" path="res://Features/Run/RunMenuItem.cs" id="1_syj0f"]
[ext_resource type="Texture2D" uid="uid://bnprs1lvjyaji" path="res://Features/Run/Play.png" id="1_xfxpu"]
[ext_resource type="Texture2D" uid="uid://csj1r7s3u10ch" path="res://Features/Run/Stop.png" id="4_cd138"]
[ext_resource type="Texture2D" uid="uid://bnprs1lvjyaji" path="res://Features/Run/Resources/Play.png" id="1_xfxpu"]
[ext_resource type="Texture2D" uid="uid://csj1r7s3u10ch" path="res://Features/Run/Resources/Stop.png" id="4_cd138"]
[node name="RunMenuItem" type="HBoxContainer"]
offset_right = 40.0

View File

@@ -1,33 +1,58 @@
using System.Collections.Generic;
using System.Linq;
using GDExtensionBindgen;
using Godot;
using SharpIDE.Application.Features.Events;
using SharpIDE.Application.Features.SolutionDiscovery.VsPersistence;
namespace SharpIDE.Godot.Features.Run;
public partial class RunPanel : Control
{
private Terminal _terminal = null!;
private TabBar _tabBar = null!;
private Panel _tabsPanel = null!;
[Export]
public Texture2D RunningIcon { get; set; } = null!;
private PackedScene _runPanelTabScene = GD.Load<PackedScene>("res://Features/Run/RunPanelTab.tscn");
public override void _Ready()
{
_tabBar = GetNode<TabBar>("%TabBar");
_tabBar.ClearTabs();
_tabsPanel = GetNode<Panel>("%TabsPanel");
var test = GetNode<Control>("VBoxContainer/TabsPanel/Terminal");
_terminal = new Terminal(test);
_terminal.Write("Hello from SharpIDE.Godot!\n");
GlobalEvents.ProjectStartedRunning += async projectModel =>
{
await this.InvokeAsync(() => ProjectStartedRunning(projectModel));
};
GlobalEvents.ProjectStoppedRunning += async projectModel =>
{
await this.InvokeAsync(() => ProjectStoppedRunning(projectModel));
};
}
public override void _Process(double delta)
public void ProjectStartedRunning(SharpIdeProjectModel projectModel)
{
//_terminal.Write("a");
}
public void NewRunStarted(SharpIdeProjectModel projectModel)
{
var terminal = new Terminal();
var existingRunPanelTab = _tabsPanel.GetChildren().OfType<RunPanelTab>().SingleOrDefault(s => s.Project == projectModel);
if (existingRunPanelTab != null)
{
_tabBar.SetTabIcon(existingRunPanelTab.TabBarTab, RunningIcon);
existingRunPanelTab.ClearTerminal();
return;
}
var runPanelTab = _runPanelTabScene.Instantiate<RunPanelTab>();
runPanelTab.Project = projectModel;
_tabBar.AddTab(projectModel.Name);
_tabsPanel.AddChild(terminal);
var tabIdx = _tabBar.GetTabCount() - 1;
runPanelTab.TabBarTab = tabIdx;
_tabBar.SetTabIcon(runPanelTab.TabBarTab, RunningIcon);
_tabsPanel.AddChild(runPanelTab);
}
public void ProjectStoppedRunning(SharpIdeProjectModel projectModel)
{
var runPanelTab = _tabsPanel.GetChildren().OfType<RunPanelTab>().Single(s => s.Project == projectModel);
_tabBar.SetTabIcon(runPanelTab.TabBarTab, null);
}
}

View File

@@ -1,6 +1,7 @@
[gd_scene load_steps=2 format=3 uid="uid://bcoytt3bw0gpe"]
[gd_scene load_steps=3 format=3 uid="uid://bcoytt3bw0gpe"]
[ext_resource type="Script" uid="uid://ddivigavjclyb" path="res://Features/Run/RunPanel.cs" id="1_sq1l4"]
[ext_resource type="Texture2D" uid="uid://76nkes2imlf2" path="res://Features/Run/Resources/Running.png" id="2_tu4jg"]
[node name="RunPanel" type="Control"]
layout_mode = 3
@@ -10,8 +11,11 @@ anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_sq1l4")
RunningIcon = ExtResource("2_tu4jg")
[node name="VBoxContainer" type="VBoxContainer" parent="."]
z_index = 100
y_sort_enabled = true
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
@@ -33,10 +37,18 @@ unique_name_in_owner = true
layout_mode = 2
size_flags_vertical = 3
[node name="Terminal" type="Terminal" parent="VBoxContainer/TabsPanel"]
[node name="Label" type="Label" parent="."]
visible = false
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
offset_left = -64.0
offset_top = -11.5
offset_right = 64.0
offset_bottom = 11.5
grow_horizontal = 2
grow_vertical = 2
text = "Nothing to show"

View File

@@ -0,0 +1,24 @@
using GDExtensionBindgen;
using Godot;
using SharpIDE.Application.Features.SolutionDiscovery.VsPersistence;
namespace SharpIDE.Godot.Features.Run;
public partial class RunPanelTab : Control
{
private Terminal _terminal = null!;
public SharpIdeProjectModel Project { get; set; } = null!;
public int TabBarTab { get; set; }
public override void _Ready()
{
_terminal = new Terminal();
AddChild(_terminal);
}
public void ClearTerminal()
{
_terminal.Clear();
}
}

View File

@@ -0,0 +1 @@
uid://ouskvcd0yaub

View File

@@ -0,0 +1,20 @@
[gd_scene load_steps=2 format=3 uid="uid://cjopkm4osnp27"]
[ext_resource type="Script" uid="uid://ouskvcd0yaub" path="res://Features/Run/RunPanelTab.cs" id="1_dx3i6"]
[node name="RunPanelTab" type="Control"]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_dx3i6")
[node name="Terminal" type="Terminal" parent="."]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2

View File

@@ -1,7 +1,7 @@
[gd_scene load_steps=8 format=3 uid="uid://b2oniigcp5ew5"]
[ext_resource type="Script" uid="uid://bavypuy7b375x" path="res://IdeRoot.cs" id="1_whawi"]
[ext_resource type="Texture2D" uid="uid://bnprs1lvjyaji" path="res://Features/Run/Play.png" id="2_8x8ub"]
[ext_resource type="Texture2D" uid="uid://bnprs1lvjyaji" path="res://Features/Run/Resources/Play.png" id="2_8x8ub"]
[ext_resource type="Script" uid="uid://du2lt7r1p1qfy" path="res://SharpIdeCodeEdit.cs" id="2_qjf5e"]
[ext_resource type="FontFile" uid="uid://7jc0nj310cu6" path="res://CascadiaCode.ttf" id="2_rk34b"]
[ext_resource type="Script" uid="uid://bai53k7ongbxw" path="res://SolutionExplorerPanel.cs" id="2_tcy02"]

View File

@@ -12,8 +12,15 @@ public static class NodeExtensions
//WorkerThreadPool.AddTask();
Callable.From(() =>
{
workItem();
taskCompletionSource.SetResult();
try
{
workItem();
taskCompletionSource.SetResult();
}
catch (Exception ex)
{
taskCompletionSource.SetException(ex);
}
}).CallDeferred();
return taskCompletionSource.Task;
}