add code editor tabs
This commit is contained in:
61
src/SharpIDE.Godot/Features/CodeEditor/CodeEditorPanel.cs
Normal file
61
src/SharpIDE.Godot/Features/CodeEditor/CodeEditorPanel.cs
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
using Godot;
|
||||||
|
using SharpIDE.Application.Features.SolutionDiscovery;
|
||||||
|
using SharpIDE.Application.Features.SolutionDiscovery.VsPersistence;
|
||||||
|
|
||||||
|
namespace SharpIDE.Godot.Features.CodeEditor;
|
||||||
|
|
||||||
|
public partial class CodeEditorPanel : MarginContainer
|
||||||
|
{
|
||||||
|
[Export]
|
||||||
|
public Texture2D CsFileTexture { get; set; } = null!;
|
||||||
|
public SharpIdeSolutionModel Solution { get; set; } = null!;
|
||||||
|
private PackedScene _sharpIdeCodeEditScene = GD.Load<PackedScene>("res://Features/CodeEditor/SharpIdeCodeEdit.tscn");
|
||||||
|
private TabContainer _tabContainer = null!;
|
||||||
|
|
||||||
|
public override void _Ready()
|
||||||
|
{
|
||||||
|
_tabContainer = GetNode<TabContainer>("TabContainer");
|
||||||
|
_tabContainer.RemoveChild(_tabContainer.GetChild(0)); // Remove the default tab
|
||||||
|
_tabContainer.TabClicked += OnTabClicked;
|
||||||
|
var tabBar = _tabContainer.GetTabBar();
|
||||||
|
tabBar.TabCloseDisplayPolicy = TabBar.CloseButtonDisplayPolicy.ShowAlways;
|
||||||
|
tabBar.TabClosePressed += OnTabClosePressed;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnTabClicked(long tab)
|
||||||
|
{
|
||||||
|
var sharpIdeFile = _tabContainer.GetChild<SharpIdeCodeEdit>((int)tab).SharpIdeFile;
|
||||||
|
GodotGlobalEvents.InvokeFileExternallySelected(sharpIdeFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnTabClosePressed(long tabIndex)
|
||||||
|
{
|
||||||
|
var tab = _tabContainer.GetChild<Control>((int)tabIndex);
|
||||||
|
_tabContainer.RemoveChild(tab);
|
||||||
|
tab.QueueFree();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task SetSharpIdeFile(SharpIdeFile file)
|
||||||
|
{
|
||||||
|
var existingTab = _tabContainer.GetChildren().OfType<SharpIdeCodeEdit>().FirstOrDefault(t => t.SharpIdeFile == file);
|
||||||
|
if (existingTab is not null)
|
||||||
|
{
|
||||||
|
var existingTabIndex = existingTab.GetIndex();
|
||||||
|
if (existingTabIndex == _tabContainer.CurrentTab) return;
|
||||||
|
await this.InvokeAsync(() => _tabContainer.CurrentTab = existingTabIndex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var newTab = _sharpIdeCodeEditScene.Instantiate<SharpIdeCodeEdit>();
|
||||||
|
newTab.Solution = Solution;
|
||||||
|
await this.InvokeAsync(() =>
|
||||||
|
{
|
||||||
|
_tabContainer.AddChild(newTab);
|
||||||
|
var newTabIndex = _tabContainer.GetTabCount() - 1;
|
||||||
|
_tabContainer.SetTabIcon(newTabIndex, CsFileTexture);
|
||||||
|
_tabContainer.SetTabTitle(newTabIndex, file.Name);
|
||||||
|
_tabContainer.SetTabTooltip(newTabIndex, file.Path);
|
||||||
|
_tabContainer.CurrentTab = newTabIndex;
|
||||||
|
});
|
||||||
|
await newTab.SetSharpIdeFile(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
uid://cy7erscaagrtj
|
||||||
@@ -1,6 +1,12 @@
|
|||||||
[gd_scene load_steps=2 format=3 uid="uid://c5dlwgcx3ubyp"]
|
[gd_scene load_steps=6 format=3 uid="uid://c5dlwgcx3ubyp"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" uid="uid://cy7erscaagrtj" path="res://Features/CodeEditor/CodeEditorPanel.cs" id="1_eraxv"]
|
||||||
[ext_resource type="PackedScene" uid="uid://cinaqbdghcvoi" path="res://Features/CodeEditor/SharpIdeCodeEdit.tscn" id="1_y4okr"]
|
[ext_resource type="PackedScene" uid="uid://cinaqbdghcvoi" path="res://Features/CodeEditor/SharpIdeCodeEdit.tscn" id="1_y4okr"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://do0edciarrnp0" path="res://Features/SolutionExplorer/Resources/CsharpFile.svg" id="2_dbtmr"]
|
||||||
|
[ext_resource type="StyleBox" uid="uid://bun830pn1vfxw" path="res://Features/CodeEditor/Resources/TabBarTabStyle.tres" id="2_m4iuw"]
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_m4iuw"]
|
||||||
|
bg_color = Color(0.11764706, 0.11764706, 0.11764706, 1)
|
||||||
|
|
||||||
[node name="CodeEditorPanel" type="MarginContainer"]
|
[node name="CodeEditorPanel" type="MarginContainer"]
|
||||||
anchors_preset = 15
|
anchors_preset = 15
|
||||||
@@ -8,7 +14,19 @@ anchor_right = 1.0
|
|||||||
anchor_bottom = 1.0
|
anchor_bottom = 1.0
|
||||||
grow_horizontal = 2
|
grow_horizontal = 2
|
||||||
grow_vertical = 2
|
grow_vertical = 2
|
||||||
|
script = ExtResource("1_eraxv")
|
||||||
|
CsFileTexture = ExtResource("2_dbtmr")
|
||||||
|
|
||||||
[node name="SharpIdeCodeEdit" parent="." instance=ExtResource("1_y4okr")]
|
[node name="TabContainer" type="TabContainer" parent="."]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
delimiter_strings = Array[String](["\" \"", "' '"])
|
theme_override_constants/side_margin = 0
|
||||||
|
theme_override_constants/icon_max_width = 22
|
||||||
|
theme_override_font_sizes/font_size = 15
|
||||||
|
theme_override_styles/tabbar_background = SubResource("StyleBoxFlat_m4iuw")
|
||||||
|
theme_override_styles/tab_selected = ExtResource("2_m4iuw")
|
||||||
|
current_tab = 0
|
||||||
|
drag_to_rearrange_enabled = true
|
||||||
|
|
||||||
|
[node name="SharpIdeCodeEdit" parent="TabContainer" instance=ExtResource("1_y4okr")]
|
||||||
|
layout_mode = 2
|
||||||
|
metadata/_tab_index = 0
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
[gd_resource type="StyleBoxFlat" format=3 uid="uid://bun830pn1vfxw"]
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
content_margin_left = 10.0
|
||||||
|
content_margin_top = 4.0
|
||||||
|
content_margin_right = 10.0
|
||||||
|
content_margin_bottom = 4.0
|
||||||
|
bg_color = Color(0.1, 0.1, 0.1, 0.6)
|
||||||
|
border_width_bottom = 2
|
||||||
|
border_color = Color(1, 1, 1, 0.75)
|
||||||
|
corner_detail = 1
|
||||||
@@ -25,6 +25,7 @@ public partial class SharpIdeCodeEdit : CodeEdit
|
|||||||
private int _selectionEndCol;
|
private int _selectionEndCol;
|
||||||
|
|
||||||
public SharpIdeSolutionModel? Solution { get; set; }
|
public SharpIdeSolutionModel? Solution { get; set; }
|
||||||
|
public SharpIdeFile SharpIdeFile => _currentFile;
|
||||||
private SharpIdeFile _currentFile = null!;
|
private SharpIdeFile _currentFile = null!;
|
||||||
|
|
||||||
private CustomHighlighter _syntaxHighlighter = new();
|
private CustomHighlighter _syntaxHighlighter = new();
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ public partial class SolutionExplorerPanel : MarginContainer
|
|||||||
item.UncollapseTree();
|
item.UncollapseTree();
|
||||||
_tree.SetSelected(item, 0);
|
_tree.SetSelected(item, 0);
|
||||||
_tree.ScrollToItem(item, true);
|
_tree.ScrollToItem(item, true);
|
||||||
|
_tree.QueueRedraw();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using SharpIDE.Application.Features.Analysis;
|
|||||||
using SharpIDE.Application.Features.SolutionDiscovery;
|
using SharpIDE.Application.Features.SolutionDiscovery;
|
||||||
using SharpIDE.Application.Features.SolutionDiscovery.VsPersistence;
|
using SharpIDE.Application.Features.SolutionDiscovery.VsPersistence;
|
||||||
using SharpIDE.Godot.Features.BottomPanel;
|
using SharpIDE.Godot.Features.BottomPanel;
|
||||||
|
using SharpIDE.Godot.Features.CodeEditor;
|
||||||
using SharpIDE.Godot.Features.CustomControls;
|
using SharpIDE.Godot.Features.CustomControls;
|
||||||
using SharpIDE.Godot.Features.Run;
|
using SharpIDE.Godot.Features.Run;
|
||||||
using SharpIDE.Godot.Features.SolutionExplorer;
|
using SharpIDE.Godot.Features.SolutionExplorer;
|
||||||
@@ -15,7 +16,7 @@ public partial class IdeRoot : Control
|
|||||||
private Button _openSlnButton = null!;
|
private Button _openSlnButton = null!;
|
||||||
private Button _buildSlnButton = null!;
|
private Button _buildSlnButton = null!;
|
||||||
private FileDialog _fileDialog = null!;
|
private FileDialog _fileDialog = null!;
|
||||||
private SharpIdeCodeEdit _sharpIdeCodeEdit = null!;
|
private CodeEditorPanel _codeEditorPanel = null!;
|
||||||
private SolutionExplorerPanel _solutionExplorerPanel = null!;
|
private SolutionExplorerPanel _solutionExplorerPanel = null!;
|
||||||
private InvertedVSplitContainer _invertedVSplitContainer = null!;
|
private InvertedVSplitContainer _invertedVSplitContainer = null!;
|
||||||
private RunPanel _runPanel = null!;
|
private RunPanel _runPanel = null!;
|
||||||
@@ -32,7 +33,7 @@ public partial class IdeRoot : Control
|
|||||||
_buildSlnButton = GetNode<Button>("%BuildSlnButton");
|
_buildSlnButton = GetNode<Button>("%BuildSlnButton");
|
||||||
_runMenuPopup = GetNode<Popup>("%RunMenuPopup");
|
_runMenuPopup = GetNode<Popup>("%RunMenuPopup");
|
||||||
_runMenuButton = GetNode<Button>("%RunMenuButton");
|
_runMenuButton = GetNode<Button>("%RunMenuButton");
|
||||||
_sharpIdeCodeEdit = GetNode<SharpIdeCodeEdit>("%CodeEditorPanel/SharpIdeCodeEdit");
|
_codeEditorPanel = GetNode<CodeEditorPanel>("%CodeEditorPanel");
|
||||||
_fileDialog = GetNode<FileDialog>("%OpenSolutionDialog");
|
_fileDialog = GetNode<FileDialog>("%OpenSolutionDialog");
|
||||||
_solutionExplorerPanel = GetNode<SolutionExplorerPanel>("%SolutionExplorerPanel");
|
_solutionExplorerPanel = GetNode<SolutionExplorerPanel>("%SolutionExplorerPanel");
|
||||||
_runPanel = GetNode<RunPanel>("%RunPanel");
|
_runPanel = GetNode<RunPanel>("%RunPanel");
|
||||||
@@ -64,7 +65,7 @@ public partial class IdeRoot : Control
|
|||||||
|
|
||||||
private async Task OnSolutionExplorerPanelOnFileSelected(SharpIdeFile file)
|
private async Task OnSolutionExplorerPanelOnFileSelected(SharpIdeFile file)
|
||||||
{
|
{
|
||||||
await _sharpIdeCodeEdit.SetSharpIdeFile(file);
|
await _codeEditorPanel.SetSharpIdeFile(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnSlnFileSelected(string path)
|
private void OnSlnFileSelected(string path)
|
||||||
@@ -74,7 +75,7 @@ public partial class IdeRoot : Control
|
|||||||
GD.Print($"Selected: {path}");
|
GD.Print($"Selected: {path}");
|
||||||
var solutionModel = await VsPersistenceMapper.GetSolutionModel(path);
|
var solutionModel = await VsPersistenceMapper.GetSolutionModel(path);
|
||||||
_solutionExplorerPanel.SolutionModel = solutionModel;
|
_solutionExplorerPanel.SolutionModel = solutionModel;
|
||||||
_sharpIdeCodeEdit.Solution = solutionModel;
|
_codeEditorPanel.Solution = solutionModel;
|
||||||
_bottomPanelManager.Solution = solutionModel;
|
_bottomPanelManager.Solution = solutionModel;
|
||||||
Callable.From(_solutionExplorerPanel.RepopulateTree).CallDeferred();
|
Callable.From(_solutionExplorerPanel.RepopulateTree).CallDeferred();
|
||||||
RoslynAnalysis.StartSolutionAnalysis(solutionModel);
|
RoslynAnalysis.StartSolutionAnalysis(solutionModel);
|
||||||
|
|||||||
Reference in New Issue
Block a user