Skip to content

Commit

Permalink
🐛 Fix textbox multiline + implement password textbox
Browse files Browse the repository at this point in the history
  • Loading branch information
valentinbreiz committed Mar 15, 2024
1 parent bcddf15 commit 86054f3
Show file tree
Hide file tree
Showing 5 changed files with 213 additions and 65 deletions.
2 changes: 1 addition & 1 deletion SRC/Aura_OS/Properties/VersionInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ namespace Aura_OS
{
public class VersionInfo
{
public static string revision = "130320241316";
public static string revision = "150320241526";
}
}
5 changes: 5 additions & 0 deletions SRC/Aura_OS/System/Graphics/UI/GUI/Components/Component.cs
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,11 @@ public void DrawImage(Bitmap image, int x, int y)
_buffer.DrawImageAlpha(image, x, y);
}

public void DrawFilledCircle(Color color, int x, int y, int radius)
{
_buffer.DrawFilledCircle(color.ToArgb(), x, y, radius);
}

public void DrawGradient(Color color1, Color color2, int x, int y, int width, int height)
{
for (int i = 0; i < width; i++)
Expand Down
244 changes: 180 additions & 64 deletions SRC/Aura_OS/System/Graphics/UI/GUI/Components/TextBox.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

using Cosmos.System;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Aura_OS.System.Graphics.UI.GUI.Components
{
Expand All @@ -14,13 +16,15 @@ public class TextBox : Component
public string Text;
public Action Enter;
public bool Multiline = false;
public bool Password = false;

private bool _isSelected = false;
private bool _cursorVisible = true;
private DateTime _lastCursorBlink = DateTime.Now;
private const int _cursorBlinkInterval = 200;

private int _cursorPosition = 0;
private int _linePosition = 0;
private int _scrollOffset = 0;

public TextBox(int x, int y, int width, int height, string text = "") : base(x, y, width, height)
Expand All @@ -44,7 +48,15 @@ public override void HandleLeftClick()
}

_isSelected = true;
_cursorPosition = Text.Length;
if (Multiline)
{
_cursorPosition = Text.Length - Text.LastIndexOf('\n') - 1;
_linePosition = Text.Split('\n').Length - 1;
}
else
{
_cursorPosition = Text.Length;
}
AdjustScrollOffsetToEnd();
Kernel.MouseManager.FocusedComponent = this;
}
Expand All @@ -67,57 +79,19 @@ public override void Update()
switch (keyEvent.Key)
{
case ConsoleKeyEx.Backspace:
if (_cursorPosition > 0 && Text.Length > 0)
{
Text = Text.Remove(_cursorPosition - 1, 1);
_cursorPosition--;
AdjustScrollOffset();
MarkDirty();
}
HandleBackspace();
break;
case ConsoleKeyEx.Enter:
if (Multiline)
{
Text += "\n";
MarkDirty();
}
else
{
if (Enter != null)
{
Enter();
MarkDirty();
}
}
HandleEnter();
break;
case ConsoleKeyEx.LeftArrow:
if (_cursorPosition > 0)
{
_cursorPosition--;
AdjustScrollOffset();
_cursorVisible = true;

MarkDirty();
}
HandleLeftArrow();
break;
case ConsoleKeyEx.RightArrow:
if (_cursorPosition < Text.Length)
{
_cursorPosition++;
AdjustScrollOffset();
_cursorVisible = true;

MarkDirty();
}
HandleRightArrow();
break;
default:
if (char.IsLetterOrDigit(keyEvent.KeyChar) || char.IsPunctuation(keyEvent.KeyChar) || char.IsSymbol(keyEvent.KeyChar) || keyEvent.KeyChar == ' ')
{
Text = Text.Insert(_cursorPosition, keyEvent.KeyChar.ToString());
_cursorPosition++;
AdjustScrollOffset();
MarkDirty();
}
HandleDefaultKey(keyEvent);
break;
}
}
Expand All @@ -132,6 +106,147 @@ public override void Update()
}
}

private void HandleLeftArrow()
{
if (_cursorPosition > 0)
{
_cursorPosition--;
AdjustScrollOffset();
_cursorVisible = true;

MarkDirty();
}
else if (_linePosition > 0)
{
// Move to the end of the previous line
_linePosition--;
_cursorPosition = Text.Split('\n')[_linePosition].Length;
AdjustScrollOffset();
_cursorVisible = true;
MarkDirty();
}
}

private void HandleRightArrow()
{
var lines = Text.Split('\n');

if (_linePosition < lines.Length)
{
string currentLine = lines[_linePosition];
if (_cursorPosition < currentLine.Length)
{
_cursorPosition++;
AdjustScrollOffset();
_cursorVisible = true;
MarkDirty();
}
else if (_linePosition < lines.Length - 1)
{
// Move to the beginning of the next line if not on the last line
_linePosition++;
_cursorPosition = 0; // Reset cursor position for the new line
AdjustScrollOffset();
_cursorVisible = true;
MarkDirty();
}
}
}


private void HandleBackspace()
{
if (_cursorPosition > 0 || _linePosition > 0)
{
var lines = Text.Split('\n');

if (_cursorPosition == 0 && _linePosition > 0)
{
// Concatenate the current line to the end of the previous line, then remove the current line
string prevLine = lines[_linePosition - 1];
string currentLine = lines[_linePosition];
lines[_linePosition - 1] = prevLine + currentLine;
List<string> linesList = lines.ToList();
linesList.RemoveAt(_linePosition);
Text = string.Join("\n", linesList.ToArray());

_linePosition--;
_cursorPosition = prevLine.Length; // Move the cursor to the end of the previous line
}
else
{
// Normal backspace operation within the same line
string currentLine = lines[_linePosition];
string newLine = currentLine.Remove(_cursorPosition - 1, 1);
lines[_linePosition] = newLine;
Text = string.Join("\n", lines);

_cursorPosition--;
}

MarkDirty();
}
}


private void HandleEnter()
{
if (Multiline)
{
// Insert a new line at the current cursor position within the text
var lines = Text.Split('\n');
if (_linePosition < lines.Length)
{
// Inserting within existing lines
lines[_linePosition] = lines[_linePosition].Insert(_cursorPosition, "\n");
Text = string.Join("\n", lines);
}
else
{
// Appending a new line at the end
Text += "\n";
}

_linePosition++;
_cursorPosition = 0; // Reset cursor position for the new line
MarkDirty();
}
else
{
Enter?.Invoke();
MarkDirty();
}
}

private void HandleDefaultKey(KeyEvent keyEvent)
{
if (char.IsLetterOrDigit(keyEvent.KeyChar) || char.IsPunctuation(keyEvent.KeyChar) || char.IsSymbol(keyEvent.KeyChar) || keyEvent.KeyChar == ' ')
{
if (Multiline)
{
// Find the correct line and position to insert the character
var lines = Text.Split('\n');
if (_linePosition < lines.Length)
{
lines[_linePosition] = lines[_linePosition].Insert(_cursorPosition, keyEvent.KeyChar.ToString());
Text = string.Join("\n", lines);
}
else
{
// If for some reason the line position is out of bounds, append the character
Text += keyEvent.KeyChar;
}
}
else
{
Text = Text.Insert(_cursorPosition, keyEvent.KeyChar.ToString());
}
_cursorPosition++;
AdjustScrollOffset();
MarkDirty();
}
}

public override void Draw()
{
base.Draw();
Expand All @@ -141,28 +256,17 @@ public override void Draw()
string[] lines = Text.Split('\n');
int offsetY = 0 + 4;
int cursorX = 0 + 4;
int cursorY = offsetY;
int cursorY = offsetY + _linePosition * Kernel.font.Height;

for (int i = 0; i < lines.Length; i++)
{
string line = lines[i];
DrawString(line, Kernel.font, Kernel.BlackColor, cursorX, offsetY);
DrawString(line, Kernel.font, Kernel.BlackColor, cursorX, offsetY + (i * Kernel.font.Height));

if (i == lines.Length - 1)
if (_isSelected && _cursorVisible && i == _linePosition)
{
cursorY = offsetY;
cursorX += line.Length * Kernel.font.Width;
DrawFilledRectangle(Kernel.BlackColor, cursorX + (_cursorPosition * Kernel.font.Width), cursorY, 2, Kernel.font.Height);
}

offsetY += Kernel.font.Height;
}

if (_isSelected && _cursorVisible)
{
int cursorWidth = 2;
int cursorHeight = Kernel.font.Height;

DrawFilledRectangle(Kernel.BlackColor, cursorX, cursorY, cursorWidth, cursorHeight);
}
}
else
Expand All @@ -174,12 +278,24 @@ public override void Draw()
visibleText = visibleText.Substring(0, maxVisibleLength);
}

DrawString(visibleText, Kernel.font, Kernel.BlackColor, 0 + 4, 0 + 4);

if (_isSelected && _cursorVisible)
if (Password)
{
int cursorX = ((_cursorPosition - _scrollOffset) * Kernel.font.Width) + 4;
DrawFilledRectangle(Kernel.BlackColor, cursorX, 0 + 4, 2, Kernel.font.Height);
int px = 0 + 6;
for (int i = 0; i < visibleText.Length; i++)
{
DrawFilledCircle(Kernel.BlackColor, px, Height / 2 - 3/2, 3);
px += 6 + 2;
}
}
else
{
DrawString(visibleText, Kernel.font, Kernel.BlackColor, 0 + 4, 0 + 4);

if (_isSelected && _cursorVisible)
{
int cursorX = ((_cursorPosition - _scrollOffset) * Kernel.font.Width) + 4;
DrawFilledRectangle(Kernel.BlackColor, cursorX, 0 + 4, 2, Kernel.font.Height);
}
}
}
}
Expand Down
26 changes: 26 additions & 0 deletions SRC/Aura_OS/System/Graphics/UI/GUI/DirectBitmap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -431,5 +431,31 @@ public void DrawImageStretchAlpha(Bitmap image, Rectangle sourceRect, Rectangle
}
}
}

/// <summary>
/// Draws a filled circle at the given coordinates with the given radius.
/// </summary>
/// <param name="color">The color to draw with.</param>
/// <param name="x0">The X center coordinate.</param>
/// <param name="y0">The Y center coordinate.</param>
/// <param name="radius">The radius of the circle to draw.</param>
public void DrawFilledCircle(int color, int x0, int y0, int radius)
{
for (int y = -radius; y <= radius; y++)
{
for (int x = -radius; x <= radius; x++)
{
if (x * x + y * y <= radius * radius)
{
int drawX = x0 + x;
int drawY = y0 + y;
if (drawX >= 0 && drawX < Width && drawY >= 0 && drawY < Height)
{
SetPixelAlpha(drawX, drawY, color);
}
}
}
}
}
}
}
1 change: 1 addition & 0 deletions SRC/Aura_OS/System/Graphics/UI/GUI/LoginScreen.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public LoginScreen(int x, int y, int width, int height) : base(x, y, width, heig
_password = new TextBox(3, 3, 200, 23, "");
_password.X = _username.X;
_password.Y = _username.Y + 23 + 6;
_password.Password = true;

AddChild(_password);

Expand Down

0 comments on commit 86054f3

Please sign in to comment.