Implementing Text Input Form and it's features.

This commit is contained in:
2025-01-07 19:09:37 -05:00
parent 9867f49ebf
commit bc8ba3ed02
7 changed files with 183 additions and 14 deletions

View File

@@ -31,6 +31,16 @@ endif()
set_target_properties(JUI PROPERTIES LINKER_LANGUAGE CXX)
CPMAddPackage(
NAME jlog
URL https://git.redacted.cc/josh/jlog/archive/Prerelease-17.zip
)
CPMAddPackage(
NAME mcolor
URL https://git.redacted.cc/maxine/mcolor/archive/Prerelease-5.zip
)
CPMAddPackage(
NAME Event
URL https://git.redacted.cc/josh/Event/archive/Release-12.zip
@@ -38,22 +48,17 @@ CPMAddPackage(
CPMAddPackage(
NAME J3ML
URL https://git.redacted.cc/josh/j3ml/archive/3.4.3.zip
)
CPMAddPackage(
NAME jlog
URL https://git.redacted.cc/josh/jlog/archive/Prerelease-16.zip
URL https://git.redacted.cc/josh/j3ml/archive/3.4.5.zip
)
CPMAddPackage(
NAME ReWindow
URL https://git.redacted.cc/Redacted/ReWindow/archive/Prerelease-26.zip
URL https://git.redacted.cc/Redacted/ReWindow/archive/Prerelease-30.zip
)
CPMAddPackage(
NAME JGL
URL https://git.redacted.cc/josh/JGL/archive/Prerelease-42.zip
URL https://git.redacted.cc/josh/JGL/archive/Prerelease-46.zip
)
target_include_directories(JUI PUBLIC ${Event_SOURCE_DIR}/include)

View File

@@ -19,6 +19,7 @@
#include <Color3.hpp>
#include <Color4.hpp>
#include <JGL/JGL.h>
#include <rewindow/types/key.h>
using namespace JGL;
@@ -318,7 +319,11 @@ namespace JUI
/// See ReWindowIntegrationDemo for an example.
virtual void ObserveMouseInput(MouseButton btn, bool pressed);
//virtual void ObserveKeyInput()
/// Informs a widget that a key has been pressed or released.
/// This is designed in such a way that the end-user can plug this into their existing code.
/// The user should call this on their Scene instances only. JUI will handle the rest.
/// See ReWindowIntegrationDemo for an example.
virtual void ObserveKeyInput(Key key, bool pressed);
protected:
void DrawChildWidgets();
void UpdateChildWidgets(float delta);

View File

@@ -9,15 +9,43 @@
/// @desc A box that accepts user keyboard input.
/// @edit 2024-08-02
#pragma once
#include <JUI/Mixins/Clickable.hpp>
#include "TextRect.hpp"
namespace JUI
{
class TextInputForm : public TextRect
class TextInputForm : public TextRect, public Clickable
{
public:
TextInputForm();
TextInputForm(Widget* parent);
void Update(float elapsed) override;
void Draw() override;
void ObserveKeyInput(Key key, bool pressed) override;
void ObserveMouseInput(MouseButton btn, bool pressed) override;
void ObserveMouseMovement(const Vector2 &latest_known_pos) override;
protected:
bool clear_text_on_return;
bool focused = false;
bool selection_enabled;
bool selection_active;
int selection_start_index;
int selection_end_index;
int cursor_position = 0;
std::string input_buffer;
float cursor_blink_time = 0.f;
private:
};
}

View File

@@ -23,6 +23,7 @@
#include <JUI/Widgets/ScrollingRect.hpp>
#include <JUI/Widgets/UtilityBar.hpp>
#include <JUI/Widgets/Checkbox.hpp>
#include <JUI/Widgets/TextInputForm.hpp>
#include <rewindow/types/window.h>
JUI::Scene* scene;
@@ -102,6 +103,10 @@ JUI::Scene* CreateScene() {
auto* check1 = new Checkbox(checkbox_horiz);
auto* input_form = new TextInputForm(s1_vert);
input_form->Size({0,30, 1, 0});
input_form->SetContent("This Diqq");
//auto* main_wnd = new Window(root);
//auto* left = new HorizontalListLayout();
@@ -375,9 +380,13 @@ int main()
window->OnMouseButtonDownEvent += [&] (MouseButtonDownEvent e) {};
window->OnKeyDownEvent += [&] (KeyDownEvent e) {};
window->OnKeyDownEvent += [&] (KeyDownEvent e) {
scene->ObserveKeyInput(e.key, true);
};
window->OnKeyUpEvent += [&] (KeyUpEvent e) {};
window->OnKeyUpEvent += [&] (KeyUpEvent e) {
scene->ObserveKeyInput(e.key, false);
};
while (window->IsAlive()) {
//window->PollEvents();

View File

@@ -382,6 +382,13 @@ namespace JUI {
}
}
void Widget::ObserveKeyInput(Key key, bool pressed) {
for (Widget* child : children) {
child->ObserveKeyInput(key, pressed);
}
}
bool Widget::IsAncestorOf(Widget *descendant) const {
if (descendant == nullptr)
return false;

View File

@@ -5,7 +5,7 @@ namespace JUI
{
ScrollingRect::ScrollingRect() : Rect() {
canvas = new JGL::RenderTarget(canvas_size, {0,0,0,0});
canvas = new JGL::RenderTarget(Vector2i(canvas_size.x, canvas_size.y));
}
ScrollingRect::ScrollingRect(Widget *parent) : ScrollingRect()

View File

@@ -1,2 +1,117 @@
#include <JUI/Widgets/TextInputForm.hpp>
#include <rewindow/inputservice.hpp>
namespace JUI {
TextInputForm::TextInputForm() : TextRect(), Clickable() { }
TextInputForm::TextInputForm(Widget* parent) : TextInputForm() {
this->Parent(parent);
}
void TextInputForm::ObserveMouseMovement(const Vector2 &latest_known_pos) {
Widget::ObserveMouseMovement(latest_known_pos);
}
void TextInputForm::ObserveMouseInput(MouseButton btn, bool pressed) {
Widget::ObserveMouseInput(btn, pressed);
if (pressed && btn == MouseButton::Left) {
if (IsMouseInside())
focused = true;
else
focused = false;
}
}
void TextInputForm::Draw() {
TextRect::Draw();
}
void TextInputForm::Update(float elapsed) {
TextRect::Update(elapsed);
// TODO: Make cursor actually blink
if (focused) {
cursor_blink_time += elapsed;
if (std::fmod( cursor_blink_time, 2) < 1) {
std::string result = input_buffer;
result.insert(cursor_position, 1, '|');
SetContent(result);
} else {
SetContent(input_buffer);
}
}
}
std::string uppercase(const std::string& input) {
std::string s = input;
std::ranges::transform(s, s.begin(), ::toupper);
return s;
}
std::string lowercase(const std::string& input) {
std::string s = input;
std::ranges::transform(s, s.begin(), ::tolower);
return s;
}
void TextInputForm::ObserveKeyInput(Key key, bool pressed) {
Widget::ObserveKeyInput(key, pressed);
if (!pressed)
return;
if (!focused)
return;
// TODO: Text Selection
// TODO: Support Copy
// TODO: Support Paste
// TODO: Support Cut
// TODO: Support insert at cursor
// TODO: Simulate key repeat.
if (key == Keys::Return || key == Keys::NumPadReturn) {
if (clear_text_on_return) {
input_buffer = "";
cursor_position = 0;
}
return;
}
if (key == Keys::LeftArrow) {
cursor_blink_time -= 1;
}
if (key == Keys::RightArrow) {
cursor_blink_time += 1;
}
if (key == Keys::LeftShift || key == Keys::RightShift || key == Keys::LeftControl || key == Keys::RightControl
|| key == Keys::LeftAlt || key == Keys::RightAlt || key == Keys::Super || key == Keys::Escape
|| key == Keys::F1 || key == Keys::F2 || key == Keys::F3 || key == Keys::F4 || key == Keys::F5 || key == Keys::F6
|| key == Keys::F7 || key == Keys::F8 || key == Keys::F9 || key == Keys::F10 || key == Keys::F11 || key == Keys::F12) {
return;
}
if (key == Keys::Backspace) {
input_buffer = input_buffer.substr(0, input_buffer.length()-1);
cursor_position--;
} else {
if (InputService::IsKeyDown(Keys::LeftShift) || InputService::IsKeyDown(Keys::RightShift)) {
input_buffer = input_buffer + uppercase( key.Mnemonic);
cursor_position++;
} else {
input_buffer = input_buffer + lowercase( key.Mnemonic);
cursor_position++;
}
//SetContent(GetContent() + key.Mnemonic);
}
}
}