Skip to content

Commit

Permalink
**Simplify UI controls and consolidate HttpMessage namespace**
Browse files Browse the repository at this point in the history
Removed PasswordInput.cs. Refactored JsonRendererTreeView.cs to be public and added EditorBrowsable attribute. Introduced IPageFactory, PageFactory, and related pages for dynamic page creation. Relocated HttpResponseMessageControl.cs and updated its rendering logic. Added several new UI components and test windows for enhancing functionality.
  • Loading branch information
frankhaugen committed Aug 14, 2024
1 parent 5814c94 commit 9e1786d
Show file tree
Hide file tree
Showing 80 changed files with 1,862 additions and 133 deletions.
10 changes: 10 additions & 0 deletions Frank.Wpf.Controls.Code/CSharpBeautifier.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace Frank.Wpf.Controls.Code;

public class CSharpBeautifier : CodeBeautifierBase
{
public override string Beautify(string code)
{
// Placeholder: Implement C# specific beautification logic
return IndentLines(code);
}
}
5 changes: 5 additions & 0 deletions Frank.Wpf.Controls.Code/CodeArea.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,9 @@ public CodeArea(IHighlightingDefinition highlightingDefinition)
WordWrap = true;
VerticalScrollBarVisibility = ScrollBarVisibility.Auto;
}

public void Beautify(ICodeBeautifier codeBeautifier)
{
Text = codeBeautifier.Beautify(Text);
}
}
16 changes: 16 additions & 0 deletions Frank.Wpf.Controls.Code/CodeBeautifierBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
namespace Frank.Wpf.Controls.Code;

public abstract class CodeBeautifierBase : ICodeBeautifier
{
public abstract string Beautify(string code);

protected string IndentLines(string code, int indentLevel = 4)
{
var lines = code.Split('\n');
for (int i = 0; i < lines.Length; i++)
{
lines[i] = new string(' ', indentLevel) + lines[i].Trim();
}
return string.Join("\n", lines);
}
}
6 changes: 6 additions & 0 deletions Frank.Wpf.Controls.Code/IBeautificationTrigger.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace Frank.Wpf.Controls.Code;

public interface IBeautificationTrigger
{
bool ShouldBeautify(string code);
}
6 changes: 6 additions & 0 deletions Frank.Wpf.Controls.Code/ICodeBeautifier.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace Frank.Wpf.Controls.Code;

public interface ICodeBeautifier
{
string Beautify(string code);
}
16 changes: 16 additions & 0 deletions Frank.Wpf.Controls.Code/JsonBeautifier.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System.Text.Json;

namespace Frank.Wpf.Controls.Code;

public class JsonBeautifier : CodeBeautifierBase
{
public override string Beautify(string code)
{
// Example using System.Text.Json for formatting JSON
var jsonElement = JsonSerializer.Deserialize<JsonElement>(code);
return JsonSerializer.Serialize(jsonElement, new JsonSerializerOptions
{
WriteIndented = true
});
}
}
16 changes: 16 additions & 0 deletions Frank.Wpf.Controls.Code/SimpleTrigger.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
namespace Frank.Wpf.Controls.Code;

public class SimpleTrigger : IBeautificationTrigger
{
private readonly Func<string, bool> _shouldBeautify;

public SimpleTrigger(Func<string, bool> shouldBeautify)
{
_shouldBeautify = shouldBeautify;
}

public bool ShouldBeautify(string code)
{
return _shouldBeautify(code);
}
}
13 changes: 13 additions & 0 deletions Frank.Wpf.Controls.CompletionPopup/CompletionData.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace Frank.Wpf.Controls.CompletionPopup;

public class CompletionData : ICompletionData
{
public CompletionData(string text, string description = "")
{
Text = text;
Description = description;
}

public string Text { get; }
public string Description { get; }
}
176 changes: 176 additions & 0 deletions Frank.Wpf.Controls.CompletionPopup/CompletionPopup.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Input;
using Frank.Wpf.Controls.CompletionPopup;

public class CompletionPopup : Popup
{
private readonly ListBox _completionListBox;
private ICompletionSource _completionSource;
private ICompletionTriggerRule _triggerRule;

public CompletionPopup()
{
StaysOpen = false;
_completionListBox = new ListBox();
_completionListBox.PreviewMouseLeftButtonUp += CompletionListBox_MouseUp;
_completionListBox.KeyDown += CompletionListBox_KeyDown;
Child = _completionListBox;
}

public void Initialize(TextBox textBox, ICompletionSource completionSource, ICompletionTriggerRule triggerRule)
{
_completionSource = completionSource;
_triggerRule = triggerRule;

_completionListBox.ItemTemplate = CreateVisualTemplate();

// Set PlacementTarget and PlacementMode
PlacementTarget = textBox;
Placement = PlacementMode.RelativePoint;

textBox.PreviewKeyDown += (s, e) => HandleKeyDown(e);
textBox.TextChanged += (s, e) => HandleTextChanged(textBox);
}

/// <inheritdoc />
protected override void OnOpened(EventArgs e)
{
_completionListBox.Focus();
base.OnOpened(e);
}

private void HandleTextChanged(TextBox textBox)
{
int position = textBox.CaretIndex;
string text = textBox.Text;

if (_triggerRule.ShouldTriggerCompletion(text, position))
{
var completions = _completionSource.GetCompletions(text, position);
SetCompletionData(completions);

var caretPosition = textBox.GetRectFromCharacterIndex(position);

// Position the popup relative to the caret
HorizontalOffset = caretPosition.Left;
VerticalOffset = caretPosition.Bottom;

IsOpen = true;
}
else
{
IsOpen = false;
}
}

private void HandleKeyDown(KeyEventArgs e)
{
if (IsOpen && (e.Key == Key.Up || e.Key == Key.Down))
{
e.Handled = true;
}
}

private void SetCompletionData(IEnumerable<ICompletionData> completions)
{
_completionListBox.Items.Clear();
foreach (var completion in completions)
{
_completionListBox.Items.Add(completion);
}

if (_completionListBox.Items.Count > 0)
{
_completionListBox.SelectedIndex = 0;
IsOpen = true;
}
else
{
IsOpen = false;
}
}

public string SelectedCompletion => (_completionListBox.SelectedItem as ICompletionData)?.Text;

// public event EventHandler<string> CompletionSelected;

private void CompletionListBox_MouseUp(object sender, MouseButtonEventArgs e)
{
OnCompletionSelected();
}

public DataTemplate CreateVisualTemplate()
{
var type = typeof(ICompletionData);

// Create a generic DataTemplate that relies on the interface's properties
var template = new DataTemplate(type);

// Create a TextBlock that binds to the Text property of the ICompletionData
var textBlockFactory = new FrameworkElementFactory(typeof(TextBlock));
textBlockFactory.SetBinding(TextBlock.TextProperty, new Binding(nameof(ICompletionData.Text)));

// Optionally add a tooltip or other visual elements based on the interface properties
if (type.GetProperty(nameof(ICompletionData.Description)) is not null)
{
var toolTipBinding = new Binding(nameof(ICompletionData.Description));
textBlockFactory.SetValue(FrameworkElement.ToolTipProperty, toolTipBinding);
}

template.VisualTree = textBlockFactory;

return template;
}

private void CompletionListBox_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter || e.Key == Key.Tab)
{
OnCompletionSelected();
e.Handled = true;
}
else if (e.Key == Key.Escape)
{
IsOpen = false;
}
else if (e.Key == Key.Up || e.Key == Key.Down)
{
e.Handled = false; // Let the ListBox handle up/down navigation
}
else
{
IsOpen = false;
}
}

private void OnCompletionSelected()
{
if (_completionListBox.SelectedItem != null)
{
CompletionPopup_CompletionSelected(this, SelectedCompletion);
IsOpen = false;
}
}


private void CompletionPopup_CompletionSelected(object? sender, string completion)
{
var popup = sender as CompletionPopup;
if (popup?.PlacementTarget is not TextBox textBox)
return;

int position = textBox.CaretIndex;

// Find the start of the word being completed
int wordStart = textBox.Text.LastIndexOf('.', position - 1) + 1;

textBox.Text = textBox.Text.Remove(wordStart, position - wordStart);
textBox.Text = textBox.Text.Insert(wordStart, completion);
textBox.CaretIndex = wordStart + completion.Length;

textBox.Focus();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<Description>A WPF control that provides a completion popup for text editors.</Description>
</PropertyGroup>

</Project>
7 changes: 7 additions & 0 deletions Frank.Wpf.Controls.CompletionPopup/ICompletionData.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Frank.Wpf.Controls.CompletionPopup;

public interface ICompletionData
{
string Text { get; }
string Description { get; }
}
6 changes: 6 additions & 0 deletions Frank.Wpf.Controls.CompletionPopup/ICompletionSource.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace Frank.Wpf.Controls.CompletionPopup;

public interface ICompletionSource
{
IEnumerable<ICompletionData> GetCompletions(string text, int position);
}
6 changes: 6 additions & 0 deletions Frank.Wpf.Controls.CompletionPopup/ICompletionTriggerRule.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace Frank.Wpf.Controls.CompletionPopup;

public interface ICompletionTriggerRule
{
bool ShouldTriggerCompletion(string text, int position);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\Frank.Wpf.Controls.SimpleInputs\Frank.Wpf.Controls.SimpleInputs.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Frank.Http" Version="1.1.0" />
</ItemGroup>

</Project>
47 changes: 47 additions & 0 deletions Frank.Wpf.Controls.HttpMessage/HttpRequestControl.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using System.Net.Http;
using System.Windows.Controls;
using Frank.Http.Abstractions;

namespace Frank.Wpf.Controls.HttpMessage;

public class HttpRequestControl : UserControl
{
private readonly IRestClient _restClient;
private HttpRequestMessageControl? _httpRequestMessageControl;
private HttpResponseMessageControl? _httpResponseMessageControl;

public HttpRequestControl(IRestClient restClient)
{
_restClient = restClient;
}

public required HttpRequestMessage HttpRequestMessage
{
get => _httpRequestMessageControl!.HttpRequestMessage;
set
{
if (_httpRequestMessageControl == null)
{
_httpRequestMessageControl = new HttpRequestMessageControl();
Content = _httpRequestMessageControl;
}
_httpRequestMessageControl.HttpRequestMessage = value;
}
}

public HttpResponseMessage? HttpResponseMessage
{
get => _httpResponseMessageControl?.HttpResponseMessage;
private set
{
if (_httpResponseMessageControl == null)
{
_httpResponseMessageControl = new HttpResponseMessageControl();
Content = _httpResponseMessageControl;
}
_httpResponseMessageControl.HttpResponseMessage = value;
}
}

public async Task SendAsync(CancellationToken cancellationToken = default) => HttpResponseMessage = await _restClient.SendAsync(HttpRequestMessage, cancellationToken);
}
Loading

0 comments on commit 9e1786d

Please sign in to comment.