refactor: add GUI instance reference to UI nodes

This commit is contained in:
MihailRis
2025-04-02 14:55:53 +03:00
parent 74a94f869c
commit 4c48afbb90
70 changed files with 1133 additions and 832 deletions
+2 -1
View File
@@ -26,12 +26,13 @@ namespace gui {
}
protected:
BasePanel(
GUI& gui,
glm::vec2 size,
glm::vec4 padding = glm::vec4(0.0f),
float interval = 2.0f,
Orientation orientation = Orientation::vertical
)
: Container(std::move(size)),
: Container(gui, std::move(size)),
padding(std::move(padding)),
interval(interval) {
}
+24 -13
View File
@@ -3,17 +3,23 @@
#include <utility>
#include "Label.hpp"
#include "graphics/core/DrawContext.hpp"
#include "graphics/core/Batch2D.hpp"
#include "graphics/core/DrawContext.hpp"
using namespace gui;
Button::Button(const std::shared_ptr<UINode>& content, glm::vec4 padding)
: Panel(glm::vec2(), padding, 0) {
Button::Button(
GUI& gui, const std::shared_ptr<UINode>& content, glm::vec4 padding
)
: Panel(gui, glm::vec2(), padding, 0) {
glm::vec4 margin = getMargin();
setSize(content->getSize()+
glm::vec2(padding[0]+padding[2]+margin[0]+margin[2],
padding[1]+padding[3]+margin[1]+margin[3]));
setSize(
content->getSize() +
glm::vec2(
padding[0] + padding[2] + margin[0] + margin[2],
padding[1] + padding[3] + margin[1] + margin[3]
)
);
add(content);
setScrollable(false);
setHoverColor(glm::vec4(0.05f, 0.1f, 0.15f, 0.75f));
@@ -22,15 +28,16 @@ Button::Button(const std::shared_ptr<UINode>& content, glm::vec4 padding)
}
Button::Button(
GUI& gui,
const std::wstring& text,
glm::vec4 padding,
glm::vec4 padding,
const onaction& action,
glm::vec2 size
) : Panel(size, padding, 0)
{
)
: Panel(gui, size, padding, 0) {
if (size.y < 0.0f) {
size = glm::vec2(
glm::max(padding.x + padding.z + text.length()*8, size.x),
glm::max(padding.x + padding.z + text.length() * 8, size.x),
glm::max(padding.y + padding.w + 16, size.y)
);
}
@@ -41,9 +48,11 @@ Button::Button(
}
setScrollable(false);
label = std::make_shared<Label>(text);
label = std::make_shared<Label>(gui, text);
label->setAlign(Align::center);
label->setSize(size-glm::vec2(padding.z+padding.x, padding.w+padding.y));
label->setSize(
size - glm::vec2(padding.z + padding.x, padding.w + padding.y)
);
label->setInteractive(false);
add(label);
setHoverColor(glm::vec4(0.05f, 0.1f, 0.15f, 0.75f));
@@ -73,7 +82,9 @@ Button* Button::textSupplier(wstringsupplier supplier) {
void Button::refresh() {
Panel::refresh();
if (label) {
label->setSize(size-glm::vec2(padding.z+padding.x, padding.w+padding.y));
label->setSize(
size - glm::vec2(padding.z + padding.x, padding.w + padding.y)
);
}
}
+13 -7
View File
@@ -9,13 +9,19 @@ namespace gui {
protected:
std::shared_ptr<Label> label;
public:
Button(const std::shared_ptr<UINode>& content,
glm::vec4 padding=glm::vec4(2.0f));
Button(const std::wstring& text,
glm::vec4 padding,
const onaction& action,
glm::vec2 size=glm::vec2(-1));
Button(
GUI& gui,
const std::shared_ptr<UINode>& content,
glm::vec4 padding = glm::vec4(2.0f)
);
Button(
GUI& gui,
const std::wstring& text,
glm::vec4 padding,
const onaction& action,
glm::vec2 size = glm::vec2(-1)
);
virtual void drawBackground(
const DrawContext& pctx, const Assets& assets
+2 -1
View File
@@ -4,7 +4,8 @@
#include "graphics/core/DrawContext.hpp"
#include "graphics/core/Texture.hpp"
gui::Canvas::Canvas(ImageFormat inFormat, glm::uvec2 inSize) : UINode(inSize) {
gui::Canvas::Canvas(GUI& gui, ImageFormat inFormat, glm::uvec2 inSize)
: UINode(gui, inSize) {
auto data = std::make_shared<ImageData>(inFormat, inSize.x, inSize.y);
mTexture = Texture::from(data.get());
mData = std::move(data);
+1 -1
View File
@@ -9,7 +9,7 @@ class Texture;
namespace gui {
class Canvas final : public UINode {
public:
explicit Canvas(ImageFormat inFormat, glm::uvec2 inSize);
explicit Canvas(GUI& gui, ImageFormat inFormat, glm::uvec2 inSize);
~Canvas() override = default;
+12 -9
View File
@@ -2,13 +2,14 @@
#include <utility>
#include "graphics/core/DrawContext.hpp"
#include "graphics/core/Batch2D.hpp"
#include "Label.hpp"
#include "graphics/core/Batch2D.hpp"
#include "graphics/core/DrawContext.hpp"
using namespace gui;
CheckBox::CheckBox(bool checked) : UINode(glm::vec2(32.0f)), checked(checked) {
CheckBox::CheckBox(GUI& gui, bool checked)
: UINode(gui, glm::vec2(32.0f)), checked(checked) {
setColor({0.0f, 0.0f, 0.0f, 0.5f});
setHoverColor({0.05f, 0.1f, 0.2f, 0.75f});
}
@@ -24,7 +25,7 @@ void CheckBox::draw(const DrawContext& pctx, const Assets&) {
batch->rect(pos.x, pos.y, size.x, size.y);
}
void CheckBox::mouseRelease(GUI*, int, int) {
void CheckBox::mouseRelease(int, int) {
checked = !checked;
if (consumer) {
consumer(checked);
@@ -44,15 +45,17 @@ CheckBox* CheckBox::setChecked(bool flag) {
return this;
}
FullCheckBox::FullCheckBox(const std::wstring& text, glm::vec2 size, bool checked)
: Panel(size),
checkbox(std::make_shared<CheckBox>(checked)),
label(std::make_shared<Label>(text)) {
FullCheckBox::FullCheckBox(
GUI& gui, const std::wstring& text, glm::vec2 size, bool checked
)
: Panel(gui, size),
checkbox(std::make_shared<CheckBox>(gui, checked)),
label(std::make_shared<Label>(gui, text)) {
setColor(glm::vec4(0.0f));
setOrientation(Orientation::horizontal);
add(checkbox);
label->setMargin(glm::vec4(5.f, 5.f, 0.f, 0.f));
add(label);
}
+12 -7
View File
@@ -2,8 +2,8 @@
#include <utility>
#include "Panel.hpp"
#include "Label.hpp"
#include "Panel.hpp"
namespace gui {
class CheckBox : public UINode {
@@ -13,11 +13,12 @@ namespace gui {
boolconsumer consumer = nullptr;
bool checked = false;
public:
CheckBox(bool checked=false);
explicit CheckBox(GUI& gui, bool checked = false);
virtual void draw(const DrawContext& pctx, const Assets& assets) override;
virtual void draw(const DrawContext& pctx, const Assets& assets)
override;
virtual void mouseRelease(GUI*, int x, int y) override;
virtual void mouseRelease(int x, int y) override;
virtual void setSupplier(boolsupplier supplier);
virtual void setConsumer(boolconsumer consumer);
@@ -25,8 +26,7 @@ namespace gui {
virtual CheckBox* setChecked(bool flag);
virtual bool isChecked() const {
if (supplier)
return supplier();
if (supplier) return supplier();
return checked;
}
};
@@ -36,7 +36,12 @@ namespace gui {
std::shared_ptr<CheckBox> checkbox;
std::shared_ptr<Label> label;
public:
FullCheckBox(const std::wstring& text, glm::vec2 size, bool checked=false);
explicit FullCheckBox(
GUI& gui,
const std::wstring& text,
glm::vec2 size,
bool checked = false
);
virtual void setSupplier(boolsupplier supplier) {
checkbox->setSupplier(std::move(supplier));
+5 -5
View File
@@ -8,7 +8,7 @@
using namespace gui;
Container::Container(glm::vec2 size) : UINode(size) {
Container::Container(GUI& gui, glm::vec2 size) : UINode(gui, size) {
actualLength = size.y;
setColor(glm::vec4());
}
@@ -41,8 +41,8 @@ std::shared_ptr<UINode> Container::getAt(const glm::vec2& pos) {
return UINode::getAt(pos);
}
void Container::mouseMove(GUI* gui, int x, int y) {
UINode::mouseMove(gui, x, y);
void Container::mouseMove(int x, int y) {
UINode::mouseMove(x, y);
if (!scrollable) {
return;
}
@@ -65,8 +65,8 @@ void Container::mouseMove(GUI* gui, int x, int y) {
prevScrollY = y;
}
void Container::mouseRelease(GUI* gui, int x, int y) {
UINode::mouseRelease(gui, x, y);
void Container::mouseRelease(int x, int y) {
UINode::mouseRelease(x, y);
prevScrollY = -1;
}
+4 -4
View File
@@ -7,7 +7,7 @@
#include <vector>
namespace gui {
class Container : public UINode, public util::ObjectsKeeper {
class Container : public UINode, public ::util::ObjectsKeeper {
int prevScrollY = -1;
protected:
std::vector<std::shared_ptr<UINode>> nodes;
@@ -22,7 +22,7 @@ namespace gui {
return prevScrollY != -1;
}
public:
Container(glm::vec2 size);
Container(GUI& gui, glm::vec2 size);
virtual ~Container();
virtual void act(float delta) override;
@@ -44,8 +44,8 @@ namespace gui {
virtual void refresh() override;
void setScroll(int scroll);
virtual void mouseMove(GUI*, int x, int y) override;
virtual void mouseRelease(GUI*, int x, int y) override;
virtual void mouseMove(int x, int y) override;
virtual void mouseRelease(int x, int y) override;
const std::vector<std::shared_ptr<UINode>>& getNodes() const;
};
+23 -11
View File
@@ -2,23 +2,24 @@
#include <utility>
#include "graphics/core/DrawContext.hpp"
#include "graphics/core/Batch2D.hpp"
#include "graphics/core/Texture.hpp"
#include "graphics/core/Atlas.hpp"
#include "assets/Assets.hpp"
#include "graphics/core/Atlas.hpp"
#include "graphics/core/Batch2D.hpp"
#include "graphics/core/DrawContext.hpp"
#include "graphics/core/Texture.hpp"
#include "maths/UVRegion.hpp"
using namespace gui;
Image::Image(std::string texture, glm::vec2 size) : UINode(size), texture(std::move(texture)) {
Image::Image(GUI& gui, std::string texture, glm::vec2 size)
: UINode(gui, size), texture(std::move(texture)) {
setInteractive(false);
}
void Image::draw(const DrawContext& pctx, const Assets& assets) {
glm::vec2 pos = calcPos();
auto batch = pctx.getBatch2D();
Texture* texture = nullptr;
auto separator = this->texture.find(':');
if (separator == std::string::npos) {
@@ -30,14 +31,16 @@ void Image::draw(const DrawContext& pctx, const Assets& assets) {
} else {
auto atlasName = this->texture.substr(0, separator);
if (auto atlas = assets.get<Atlas>(atlasName)) {
if (auto region = atlas->getIf(this->texture.substr(separator+1))) {
if (auto region =
atlas->getIf(this->texture.substr(separator + 1))) {
texture = atlas->getTexture();
batch->texture(atlas->getTexture());
batch->setRegion(*region);
if (autoresize) {
setSize(glm::vec2(
texture->getWidth()*region->getWidth(),
texture->getHeight()*region->getHeight()));
texture->getWidth() * region->getWidth(),
texture->getHeight() * region->getHeight()
));
}
} else {
batch->texture(nullptr);
@@ -45,8 +48,17 @@ void Image::draw(const DrawContext& pctx, const Assets& assets) {
}
}
batch->rect(
pos.x, pos.y, size.x, size.y,
0, 0, 0, UVRegion(), false, true, calcColor()
pos.x,
pos.y,
size.x,
size.y,
0,
0,
0,
UVRegion(),
false,
true,
calcColor()
);
}
+1 -1
View File
@@ -8,7 +8,7 @@ namespace gui {
std::string texture;
bool autoresize = false;
public:
Image(std::string texture, glm::vec2 size=glm::vec2(32,32));
Image(GUI& gui, std::string texture, glm::vec2 size=glm::vec2(32,32));
virtual void draw(const DrawContext& pctx, const Assets& assets) override;
+4 -4
View File
@@ -7,10 +7,10 @@
using namespace gui;
InputBindBox::InputBindBox(Binding& binding, glm::vec4 padding)
: Panel(glm::vec2(100,32), padding, 0),
InputBindBox::InputBindBox(GUI& gui, Binding& binding, glm::vec4 padding)
: Panel(gui, glm::vec2(100,32), padding, 0),
binding(binding),
label(std::make_shared<Label>(L"")) {
label(std::make_shared<Label>(gui, L"")) {
add(label);
setScrollable(false);
hoverColor = glm::vec4(0.05f, 0.1f, 0.2f, 0.75f);
@@ -25,7 +25,7 @@ void InputBindBox::drawBackground(const DrawContext& pctx, const Assets&) {
label->setText(util::str2wstr_utf8(binding.text()));
}
void InputBindBox::clicked(GUI*, mousecode button) {
void InputBindBox::clicked(mousecode button) {
if (isFocused()) {
binding.reset(button);
defocus();
+9 -5
View File
@@ -4,21 +4,25 @@
namespace gui {
class Label;
class InputBindBox : public Panel {
protected:
Binding& binding;
glm::vec4 focusedColor {0.1f, 0.15f, 0.35f, 0.75f};
std::shared_ptr<Label> label;
public:
InputBindBox(Binding& binding, glm::vec4 padding=glm::vec4(6.0f));
explicit InputBindBox(
GUI& gui, Binding& binding, glm::vec4 padding = glm::vec4(6.0f)
);
virtual void drawBackground(
const DrawContext& pctx, const Assets& assets
) override;
virtual void clicked(GUI*, mousecode button) override;
virtual void clicked(mousecode button) override;
virtual void keyPressed(keycode key) override;
virtual bool isFocuskeeper() const override {return true;}
virtual bool isFocuskeeper() const override {
return true;
}
};
}
+12 -11
View File
@@ -46,8 +46,8 @@ SlotLayout::SlotLayout(
shareFunc(std::move(shareFunc)),
rightClick(std::move(rightClick)) {}
InventoryBuilder::InventoryBuilder() {
view = std::make_shared<InventoryView>();
InventoryBuilder::InventoryBuilder(GUI& gui) : gui(gui) {
view = std::make_shared<InventoryView>(gui);
}
void InventoryBuilder::addGrid(
@@ -75,7 +75,8 @@ void InventoryBuilder::addGrid(
view->setSize(vsize);
if (addpanel) {
auto panel = std::make_shared<gui::Container>(glm::vec2(width, height));
auto panel =
std::make_shared<gui::Container>(gui, glm::vec2(width, height));
view->setColor(glm::vec4(0.122f, 0.122f, 0.122f, 0.878f));
view->add(panel, pos);
}
@@ -106,8 +107,8 @@ std::shared_ptr<InventoryView> InventoryBuilder::build() {
}
SlotView::SlotView(
SlotLayout layout
) : UINode(glm::vec2(InventoryView::SLOT_SIZE)),
GUI& gui, SlotLayout layout
) : UINode(gui, glm::vec2(InventoryView::SLOT_SIZE)),
layout(std::move(layout))
{
setColor(glm::vec4(0, 0, 0, 0.2f));
@@ -347,11 +348,11 @@ void SlotView::performRightClick(ItemStack& stack, ItemStack& grabbed) {
}
}
void SlotView::clicked(gui::GUI* gui, mousecode button) {
void SlotView::clicked(mousecode button) {
if (bound == nullptr)
return;
auto exchangeSlot =
std::dynamic_pointer_cast<SlotView>(gui->get(EXCHANGE_SLOT_NAME));
std::dynamic_pointer_cast<SlotView>(gui.get(EXCHANGE_SLOT_NAME));
if (exchangeSlot == nullptr) {
return;
}
@@ -368,8 +369,8 @@ void SlotView::clicked(gui::GUI* gui, mousecode button) {
}
}
void SlotView::onFocus(gui::GUI* gui) {
clicked(gui, mousecode::BUTTON_1);
void SlotView::onFocus() {
clicked(mousecode::BUTTON_1);
}
const std::wstring& SlotView::getTooltip() const {
@@ -398,7 +399,7 @@ ItemStack& SlotView::getStack() {
return *bound;
}
InventoryView::InventoryView() : Container(glm::vec2()) {
InventoryView::InventoryView(GUI& gui) : Container(gui, glm::vec2()) {
setColor(glm::vec4(0, 0, 0, 0.0f));
}
@@ -419,7 +420,7 @@ std::shared_ptr<SlotView> InventoryView::addSlot(const SlotLayout& layout) {
}
setSize(vsize);
auto slot = std::make_shared<SlotView>(layout);
auto slot = std::make_shared<SlotView>(gui, layout);
if (!layout.background) {
slot->setColor(glm::vec4());
}
+6 -5
View File
@@ -86,15 +86,15 @@ namespace gui {
void refreshTooltip(const ItemStack& stack, const ItemDef& item);
public:
SlotView(SlotLayout layout);
SlotView(GUI& gui, SlotLayout layout);
virtual void draw(const DrawContext& pctx, const Assets& assets) override;
void setHighlighted(bool flag);
bool isHighlighted() const;
virtual void clicked(gui::GUI*, mousecode) override;
virtual void onFocus(gui::GUI*) override;
virtual void clicked(mousecode) override;
virtual void onFocus() override;
virtual const std::wstring& getTooltip() const override;
void bind(
@@ -117,7 +117,7 @@ namespace gui {
std::vector<SlotView*> slots;
glm::vec2 origin {};
public:
InventoryView();
InventoryView(GUI& gui);
virtual ~InventoryView();
virtual void setPos(glm::vec2 pos) override;
@@ -145,9 +145,10 @@ namespace gui {
};
class InventoryBuilder {
GUI& gui;
std::shared_ptr<InventoryView> view;
public:
InventoryBuilder();
InventoryBuilder(GUI& gui);
/// @brief Add slots grid to inventory view
/// @param cols grid columns
+4 -4
View File
@@ -83,8 +83,8 @@ void LabelCache::update(std::wstring_view text, bool multiline, bool wrap) {
}
}
Label::Label(const std::string& text, std::string fontName)
: UINode(glm::vec2(text.length() * 8, 16)),
Label::Label(GUI& gui, const std::string& text, std::string fontName)
: UINode(gui, glm::vec2(text.length() * 8, 16)),
text(util::str2wstr_utf8(text)),
fontName(std::move(fontName))
{
@@ -93,8 +93,8 @@ Label::Label(const std::string& text, std::string fontName)
}
Label::Label(const std::wstring& text, std::string fontName)
: UINode(glm::vec2(text.length() * 8, 16)),
Label::Label(GUI& gui, const std::wstring& text, std::string fontName)
: UINode(gui, glm::vec2(text.length() * 8, 16)),
text(text),
fontName(std::move(fontName))
{
+2 -2
View File
@@ -63,8 +63,8 @@ namespace gui {
std::unique_ptr<FontStylesScheme> styles;
public:
Label(const std::string& text, std::string fontName=FONT_DEFAULT);
Label(const std::wstring& text, std::string fontName=FONT_DEFAULT);
Label(GUI& gui, const std::string& text, std::string fontName="normal");
Label(GUI& gui, const std::wstring& text, std::string fontName="normal");
virtual ~Label();
+1 -1
View File
@@ -5,7 +5,7 @@
using namespace gui;
Menu::Menu() : Container(glm::vec2(1)){
Menu::Menu(GUI& gui) : Container(gui, glm::vec2(1)){
}
bool Menu::has(const std::string& name) {
+1 -1
View File
@@ -21,7 +21,7 @@ namespace gui {
std::unordered_map<std::string, supplier<std::shared_ptr<UINode>>> pageSuppliers;
PageLoaderFunc pagesLoader = nullptr;
public:
Menu();
explicit Menu(GUI& gui);
/// @brief Check menu have page or page supplier
/// @param name page name
+12 -12
View File
@@ -4,14 +4,12 @@
using namespace gui;
Panel::Panel(glm::vec2 size, glm::vec4 padding, float interval)
: BasePanel(size, padding, interval, Orientation::vertical)
{
Panel::Panel(GUI& gui, glm::vec2 size, glm::vec4 padding, float interval)
: BasePanel(gui, size, padding, interval) {
setColor(glm::vec4(0.0f, 0.0f, 0.0f, 0.75f));
}
Panel::~Panel() {
}
Panel::~Panel() = default;
void Panel::setMaxLength(int value) {
maxLength = value;
@@ -46,7 +44,7 @@ void Panel::fullRefresh() {
Container::fullRefresh();
}
void Panel::add(const std::shared_ptr<UINode> &node) {
void Panel::add(const std::shared_ptr<UINode>& node) {
node->setResizing(true);
Container::add(node);
fullRefresh();
@@ -68,10 +66,10 @@ void Panel::refresh() {
for (auto& node : nodes) {
const glm::vec4 margin = node->getMargin();
y += margin.y;
float ex = x + margin.x;
node->setPos(glm::vec2(ex, y));
float width = size.x - padding.x - padding.z - margin.x - margin.z;
if (node->isResizing()) {
node->setMaxSize({width, node->getMaxSize().y});
@@ -80,7 +78,7 @@ void Panel::refresh() {
node->refresh();
glm::vec2 nodeSize = node->getSize();
y += nodeSize.y + margin.w + interval;
maxw = fmax(maxw, ex+nodeSize.x+margin.z+padding.z);
maxw = fmax(maxw, ex + nodeSize.x + margin.z + padding.z);
}
actualLength = y + padding.w;
} else {
@@ -89,11 +87,13 @@ void Panel::refresh() {
glm::vec2 nodesize = node->getSize();
const glm::vec4 margin = node->getMargin();
x += margin.x;
node->setPos(glm::vec2(x, y+margin.y));
node->setPos(glm::vec2(x, y + margin.y));
x += nodesize.x + margin.z + interval;
node->refresh();
maxh = fmax(maxh, y+margin.y+node->getSize().y+margin.w+padding.w);
maxh = fmax(
maxh, y + margin.y + node->getSize().y + margin.w + padding.w
);
}
actualLength = size.y;
}
+5 -4
View File
@@ -1,15 +1,16 @@
#pragma once
#include "commons.hpp"
#include "BasePanel.hpp"
#include "commons.hpp"
namespace gui {
class Panel : public BasePanel {
public:
Panel(
glm::vec2 size,
glm::vec4 padding=glm::vec4(0.0f),
float interval=2.0f
GUI& gui,
glm::vec2 size,
glm::vec4 padding = glm::vec4(2.0f),
float interval = 2.0f
);
virtual ~Panel();
+16 -10
View File
@@ -1,15 +1,16 @@
#pragma once
#include <glm/glm.hpp>
#include <memory>
#include "UINode.hpp"
#include "typedefs.hpp"
#include <memory>
class Assets;
class DrawContext;
namespace gui {
class Plotter : public gui::UINode {
class Plotter : public UINode {
std::unique_ptr<int[]> points;
float multiplier;
int index = 0;
@@ -17,13 +18,18 @@ namespace gui {
int dmheight;
int labelsInterval;
public:
Plotter(uint width, uint height, float multiplier, int labelsInterval)
: gui::UINode(glm::vec2(width, height)),
multiplier(multiplier),
dmwidth(width-50),
dmheight(height),
labelsInterval(labelsInterval)
{
Plotter(
GUI& gui,
uint width,
uint height,
float multiplier,
int labelsInterval
)
: UINode(gui, glm::vec2(width, height)),
multiplier(multiplier),
dmwidth(width - 50),
dmheight(height),
labelsInterval(labelsInterval) {
points = std::make_unique<int[]>(dmwidth);
}
+4 -4
View File
@@ -2,15 +2,15 @@
using namespace gui;
SplitBox::SplitBox(const glm::vec2& size, float splitPos, Orientation orientation)
: BasePanel(size, glm::vec4(), 4.0f, orientation), splitPos(splitPos) {
SplitBox::SplitBox(GUI& gui, const glm::vec2& size, float splitPos, Orientation orientation)
: BasePanel(gui, size, glm::vec4(), 4.0f, orientation), splitPos(splitPos) {
setCursor(
orientation == Orientation::vertical ? CursorShape::NS_RESIZE
: CursorShape::EW_RESIZE
);
}
void SplitBox::mouseMove(GUI*, int x, int y) {
void SplitBox::mouseMove(int x, int y) {
auto pos = calcPos();
auto size = getSize();
@@ -59,7 +59,7 @@ void SplitBox::refresh() {
}
}
void SplitBox::doubleClick(GUI*, int x, int y) {
void SplitBox::doubleClick(int x, int y) {
if (nodes.size() < 2) {
return;
}
+3 -3
View File
@@ -5,12 +5,12 @@
namespace gui {
class SplitBox : public BasePanel {
public:
SplitBox(const glm::vec2& size, float splitPos, Orientation orientation);
SplitBox(GUI& gui, const glm::vec2& size, float splitPos, Orientation orientation);
virtual void mouseMove(GUI*, int x, int y) override;
virtual void mouseMove(int x, int y) override;
virtual void refresh() override;
virtual void fullRefresh() override;
virtual void doubleClick(GUI*, int x, int y) override;
virtual void doubleClick(int x, int y) override;
private:
float splitPos;
};
+87 -69
View File
@@ -4,9 +4,12 @@
#include <sstream>
#include <utility>
#include "../GUI.hpp"
#include "../markdown.hpp"
#include "Label.hpp"
#include "assets/Assets.hpp"
#include "devtools/syntax_highlighting.hpp"
#include "engine/Engine.hpp"
#include "graphics/core/Batch2D.hpp"
#include "graphics/core/DrawContext.hpp"
#include "graphics/core/Font.hpp"
@@ -186,8 +189,9 @@ namespace gui {
};
}
TextBox::TextBox(std::wstring placeholder, glm::vec4 padding)
: Container(glm::vec2(200, 32)),
TextBox::TextBox(GUI& gui, std::wstring placeholder, glm::vec4 padding)
: Container(gui, glm::vec2(200, 32)),
inputEvents(gui.getInput()),
history(std::make_shared<ActionsHistory>()),
historian(std::make_unique<TextBoxHistorian>(*this, *history)),
padding(padding),
@@ -197,19 +201,24 @@ TextBox::TextBox(std::wstring placeholder, glm::vec4 padding)
setOnUpPressed(nullptr);
setOnDownPressed(nullptr);
setColor(glm::vec4(0.0f, 0.0f, 0.0f, 0.75f));
label = std::make_shared<Label>(L"");
label->setSize(size-glm::vec2(padding.z+padding.x, padding.w+padding.y));
label = std::make_shared<Label>(gui, L"");
label->setSize(
size - glm::vec2(padding.z + padding.x, padding.w + padding.y)
);
label->setPos(glm::vec2(
padding.x + LINE_NUMBERS_PANE_WIDTH * showLineNumbers, padding.y
));
add(label);
lineNumbersLabel = std::make_shared<Label>(L"");
lineNumbersLabel = std::make_shared<Label>(gui, L"");
lineNumbersLabel->setMultiline(true);
lineNumbersLabel->setSize(size-glm::vec2(padding.z+padding.x, padding.w+padding.y));
lineNumbersLabel->setSize(
size - glm::vec2(padding.z + padding.x, padding.w + padding.y)
);
lineNumbersLabel->setVerticalAlign(Align::top);
add(lineNumbersLabel);
setHoverColor(glm::vec4(0.05f, 0.1f, 0.2f, 0.75f));
textInitX = label->getPos().x;
@@ -342,7 +351,7 @@ void TextBox::drawBackground(const DrawContext& pctx, const Assets&) {
batch->texture(nullptr);
auto subctx = pctx.sub();
subctx.setScissors(glm::vec4(pos.x, pos.y-0.5, size.x, size.y+1));
subctx.setScissors(glm::vec4(pos.x, pos.y - 0.5, size.x, size.y + 1));
if (valid) {
if (isFocused() && !multiline) {
@@ -371,7 +380,8 @@ void TextBox::refreshLabel() {
const auto& displayText = input.empty() && !hint.empty() ? hint : getText();
if (markup == "md") {
auto [processedText, styles] = markdown::process(displayText, !focused || !editable);
auto [processedText, styles] =
markdown::process(displayText, !focused || !editable);
label->setText(std::move(processedText));
label->setStyles(std::move(styles));
} else {
@@ -380,13 +390,13 @@ void TextBox::refreshLabel() {
label->setStyles(nullptr);
}
}
if (showLineNumbers) {
if (lineNumbersLabel->getLinesNumber() != label->getLinesNumber()) {
std::wstringstream ss;
int n = 1;
for (int i = 1; i <= label->getLinesNumber(); i++) {
if (!label->isFakeLine(i-1)) {
if (!label->isFakeLine(i - 1)) {
ss << n;
n++;
}
@@ -402,11 +412,12 @@ void TextBox::refreshLabel() {
if (autoresize && font) {
auto size = getSize();
int newy = glm::min(static_cast<int>(parent->getSize().y),
static_cast<int>(
label->getLinesNumber() *
label->getLineInterval() *
font->getLineHeight()) + 1
int newy = glm::min(
static_cast<int>(parent->getSize().y),
static_cast<int>(
label->getLinesNumber() * label->getLineInterval() *
font->getLineHeight()
) + 1
);
if (newy != static_cast<int>(size.y)) {
size.y = newy;
@@ -475,7 +486,7 @@ bool TextBox::eraseSelected() {
input.substr(selectionStart, selectionEnd - selectionStart),
true
);
erase(selectionStart, selectionEnd-selectionStart);
erase(selectionStart, selectionEnd - selectionStart);
resetSelection();
onInput();
return true;
@@ -495,7 +506,7 @@ void TextBox::extendSelection(int index) {
size_t TextBox::getLineLength(uint line) const {
size_t position = label->getTextLineOffset(line);
size_t lineLength = label->getTextLineOffset(line+1)-position;
size_t lineLength = label->getTextLineOffset(line + 1) - position;
if (lineLength == 0) {
lineLength = label->getText().length() - position + 1;
}
@@ -547,7 +558,7 @@ void TextBox::setMultiline(bool multiline) {
bool TextBox::isMultiline() const {
return multiline;
}
void TextBox::setTextWrapping(bool flag) {
label->setTextWrapping(flag);
}
@@ -593,9 +604,9 @@ bool TextBox::isAutoResize() const {
return autoresize;
}
void TextBox::onFocus(GUI* gui) {
Container::onFocus(gui);
if (onEditStart){
void TextBox::onFocus() {
Container::onFocus();
if (onEditStart) {
setCaret(input.size());
onEditStart();
resetSelection();
@@ -609,7 +620,9 @@ void TextBox::reposition() {
void TextBox::refresh() {
Container::refresh();
label->setSize(size-glm::vec2(padding.z+padding.x, padding.w+padding.y));
label->setSize(
size - glm::vec2(padding.z + padding.x, padding.w + padding.y)
);
label->setPos(glm::vec2(
padding.x + LINE_NUMBERS_PANE_WIDTH * showLineNumbers + textInitX -
static_cast<int>(textOffset),
@@ -629,24 +642,27 @@ size_t TextBox::normalizeIndex(int index) {
/// @param y screen Y position
/// @return non-normalized character index
int TextBox::calcIndexAt(int x, int y) const {
if (font == nullptr)
return 0;
if (font == nullptr) return 0;
const auto& labelText = label->getText();
glm::vec2 lcoord = label->calcPos();
uint line = label->getLineByYOffset(y-lcoord.y);
line = std::min(line, label->getLinesNumber()-1);
uint line = label->getLineByYOffset(y - lcoord.y);
line = std::min(line, label->getLinesNumber() - 1);
size_t lineLength = getLineLength(line);
uint offset = 0;
while (lcoord.x + font->calcWidth(labelText, offset) < x && offset < lineLength-1) {
while (lcoord.x + font->calcWidth(labelText, offset) < x &&
offset < lineLength - 1) {
offset++;
}
return std::min(offset+label->getTextLineOffset(line), labelText.length());
return std::min(
offset + label->getTextLineOffset(line), labelText.length()
);
}
static inline std::wstring get_alphabet(wchar_t c) {
std::wstring alphabet {c};
if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '_') {
return L"abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
return L"abcdefghijklmnopqrstuvwxyz_"
L"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
} else if (c >= '0' && c <= '9') {
return L"0123456789";
}
@@ -660,7 +676,7 @@ void TextBox::tokenSelectAt(int index) {
}
int left = index;
int right = index;
std::wstring alphabet = get_alphabet(actualText.at(index));
while (left >= 0) {
if (alphabet.find(actualText.at(left)) == std::wstring::npos) {
@@ -674,23 +690,23 @@ void TextBox::tokenSelectAt(int index) {
}
right++;
}
select(left+1, right);
select(left + 1, right);
}
void TextBox::doubleClick(GUI* gui, int x, int y) {
UINode::doubleClick(gui, x, y);
tokenSelectAt(normalizeIndex(calcIndexAt(x, y)-1));
void TextBox::doubleClick(int x, int y) {
UINode::doubleClick(x, y);
tokenSelectAt(normalizeIndex(calcIndexAt(x, y) - 1));
}
void TextBox::click(GUI*, int x, int y) {
void TextBox::click(int x, int y) {
int index = normalizeIndex(calcIndexAt(x, y));
selectionStart = index;
selectionEnd = index;
selectionOrigin = index;
}
void TextBox::mouseMove(GUI* gui, int x, int y) {
Container::mouseMove(gui, x, y);
void TextBox::mouseMove(int x, int y) {
Container::mouseMove(x, y);
if (isScrolling()) {
return;
}
@@ -701,7 +717,8 @@ void TextBox::mouseMove(GUI* gui, int x, int y) {
}
void TextBox::resetMaxLocalCaret() {
maxLocalCaret = caret - label->getTextLineOffset(label->getLineByTextIndex(caret));
maxLocalCaret =
caret - label->getTextLineOffset(label->getLineByTextIndex(caret));
}
void TextBox::stepLeft(bool shiftPressed, bool breakSelection) {
@@ -709,9 +726,9 @@ void TextBox::stepLeft(bool shiftPressed, bool breakSelection) {
size_t caret = breakSelection ? selectionStart : this->caret;
if (caret > 0) {
if (caret > input.length()) {
setCaret(input.length()-1);
setCaret(input.length() - 1);
} else {
setCaret(caret-1);
setCaret(caret - 1);
}
if (shiftPressed) {
if (selectionStart == selectionEnd) {
@@ -732,7 +749,7 @@ void TextBox::stepRight(bool shiftPressed, bool breakSelection) {
uint previousCaret = this->caret;
size_t caret = breakSelection ? selectionEnd : this->caret;
if (caret < input.length()) {
setCaret(caret+1);
setCaret(caret + 1);
caretLastMove = Window::time();
if (shiftPressed) {
if (selectionStart == selectionEnd) {
@@ -753,9 +770,10 @@ void TextBox::stepDefaultDown(bool shiftPressed, bool breakSelection) {
uint previousCaret = this->caret;
uint caret = breakSelection ? selectionEnd : this->caret;
uint caretLine = label->getLineByTextIndex(caret);
if (caretLine < label->getLinesNumber()-1) {
uint offset = std::min(size_t(maxLocalCaret), getLineLength(caretLine+1)-1);
setCaret(label->getTextLineOffset(caretLine+1) + offset);
if (caretLine < label->getLinesNumber() - 1) {
uint offset =
std::min(size_t(maxLocalCaret), getLineLength(caretLine + 1) - 1);
setCaret(label->getTextLineOffset(caretLine + 1) + offset);
} else {
setCaret(input.length());
}
@@ -774,8 +792,9 @@ void TextBox::stepDefaultUp(bool shiftPressed, bool breakSelection) {
uint caret = breakSelection ? selectionStart : this->caret;
uint caretLine = label->getLineByTextIndex(caret);
if (caretLine > 0) {
uint offset = std::min(size_t(maxLocalCaret), getLineLength(caretLine-1)-1);
setCaret(label->getTextLineOffset(caretLine-1) + offset);
uint offset =
std::min(size_t(maxLocalCaret), getLineLength(caretLine - 1) - 1);
setCaret(label->getTextLineOffset(caretLine - 1) + offset);
} else {
setCaret(static_cast<size_t>(0));
}
@@ -805,7 +824,7 @@ void TextBox::onInput() {
}
void TextBox::performEditingKeyboardEvents(keycode key) {
bool shiftPressed = Events::pressed(keycode::LEFT_SHIFT);
bool shiftPressed = gui.getInput().pressed(keycode::LEFT_SHIFT);
bool breakSelection = getSelectionLength() != 0 && !shiftPressed;
if (key == keycode::BACKSPACE) {
if (!eraseSelected() && caret > 0 && input.length() > 0) {
@@ -813,8 +832,8 @@ void TextBox::performEditingKeyboardEvents(keycode key) {
caret = input.length();
}
historian->onErase(caret - 1, input.substr(caret - 1, 1));
input = input.substr(0, caret-1) + input.substr(caret);
setCaret(caret-1);
input = input.substr(0, caret - 1) + input.substr(caret);
setCaret(caret - 1);
if (validate()) {
onInput();
}
@@ -850,10 +869,11 @@ void TextBox::performEditingKeyboardEvents(keycode key) {
}
void TextBox::keyPressed(keycode key) {
const auto& inputEvents = gui.getInput();
if (editable) {
performEditingKeyboardEvents(key);
}
if (Events::pressed(keycode::LEFT_CONTROL) && key != keycode::LEFT_CONTROL) {
if (inputEvents.pressed(keycode::LEFT_CONTROL) && key != keycode::LEFT_CONTROL) {
if (controlCombinationsHandler) {
if (controlCombinationsHandler(static_cast<int>(key))) {
return;
@@ -871,7 +891,7 @@ void TextBox::keyPressed(keycode key) {
}
// Paste text from clipboard
if (key == keycode::V && editable) {
const char* text = Window::getClipboardText();
const char* text = inputEvents.getClipboardText();
if (text) {
historian->sync(); // flush buffer before combination
// Combine deleting selected text and pasing a clipboard content
@@ -924,14 +944,14 @@ std::shared_ptr<UINode> TextBox::getAt(const glm::vec2& pos) {
return UINode::getAt(pos);
}
void TextBox::setOnUpPressed(const runnable &callback) {
void TextBox::setOnUpPressed(const runnable& callback) {
if (callback == nullptr) {
onUpPressed = [this]() {
if (Events::pressed(keycode::LEFT_CONTROL)) {
if (inputEvents.pressed(keycode::LEFT_CONTROL)) {
scrolled(1);
return;
}
bool shiftPressed = Events::pressed(keycode::LEFT_SHIFT);
bool shiftPressed = inputEvents.pressed(keycode::LEFT_SHIFT);
bool breakSelection = getSelectionLength() != 0 && !shiftPressed;
stepDefaultUp(shiftPressed, breakSelection);
};
@@ -940,14 +960,14 @@ void TextBox::setOnUpPressed(const runnable &callback) {
}
}
void TextBox::setOnDownPressed(const runnable &callback) {
void TextBox::setOnDownPressed(const runnable& callback) {
if (callback == nullptr) {
onDownPressed = [this]() {
if (Events::pressed(keycode::LEFT_CONTROL)) {
if (inputEvents.pressed(keycode::LEFT_CONTROL)) {
scrolled(-1);
return;
}
bool shiftPressed = Events::pressed(keycode::LEFT_SHIFT);
bool shiftPressed = inputEvents.pressed(keycode::LEFT_SHIFT);
bool breakSelection = getSelectionLength() != 0 && !shiftPressed;
stepDefaultDown(shiftPressed, breakSelection);
};
@@ -984,7 +1004,6 @@ glm::vec4 TextBox::getFocusedColor() const {
return focusedColor;
}
void TextBox::setTextColor(glm::vec4 color) {
this->textColor = color;
}
@@ -1002,8 +1021,7 @@ glm::vec4 TextBox::getErrorColor() const {
}
const std::wstring& TextBox::getText() const {
if (input.empty())
return placeholder;
if (input.empty()) return placeholder;
return input;
}
@@ -1024,7 +1042,6 @@ void TextBox::setPlaceholder(const std::wstring& placeholder) {
this->placeholder = placeholder;
}
const std::wstring& TextBox::getHint() const {
return hint;
}
@@ -1035,7 +1052,7 @@ void TextBox::setHint(const std::wstring& text) {
std::wstring TextBox::getSelection() const {
const auto& text = label->getText();
return text.substr(selectionStart, selectionEnd-selectionStart);
return text.substr(selectionStart, selectionEnd - selectionStart);
}
size_t TextBox::getCaret() const {
@@ -1057,24 +1074,25 @@ void TextBox::setCaret(size_t position) {
uint line = rawTextCache.getLineByTextIndex(caret);
int offset = label->getLineYOffset(line) + getContentOffset().y;
uint lineHeight = font->getLineHeight()*label->getLineInterval();
uint lineHeight = font->getLineHeight() * label->getLineInterval();
if (scrollStep == 0) {
scrollStep = lineHeight;
}
if (offset < 0) {
scrolled(-glm::floor(offset / static_cast<double>(scrollStep)+0.5f));
scrolled(-glm::floor(offset / static_cast<double>(scrollStep) + 0.5f));
} else if (offset >= getSize().y) {
offset -= getSize().y;
scrolled(-glm::ceil(offset / static_cast<double>(scrollStep)+0.5f));
scrolled(-glm::ceil(offset / static_cast<double>(scrollStep) + 0.5f));
}
int lcaret = caret - rawTextCache.getTextLineOffset(line);
int realoffset =
font->calcWidth(labelText, lcaret) - static_cast<int>(textOffset) + 2;
if (realoffset-width > 0) {
setTextOffset(textOffset + realoffset-width);
if (realoffset - width > 0) {
setTextOffset(textOffset + realoffset - width);
} else if (realoffset < 0) {
setTextOffset(std::max(textOffset + realoffset, static_cast<size_t>(0)));
setTextOffset(std::max(textOffset + realoffset, static_cast<size_t>(0))
);
}
}
+7 -5
View File
@@ -9,6 +9,7 @@ class ActionsHistory;
namespace gui {
class TextBoxHistorian;
class TextBox : public Container {
const Input& inputEvents;
LabelCache rawTextCache;
std::shared_ptr<ActionsHistory> history;
std::unique_ptr<TextBoxHistorian> historian;
@@ -94,7 +95,8 @@ namespace gui {
void refreshSyntax();
public:
TextBox(
explicit TextBox(
GUI& gui,
std::wstring placeholder,
glm::vec4 padding=glm::vec4(4.0f)
);
@@ -227,11 +229,11 @@ namespace gui {
virtual bool isShowLineNumbers() const;
virtual void reposition() override;
virtual void onFocus(GUI*) override;
virtual void onFocus() override;
virtual void refresh() override;
virtual void doubleClick(GUI*, int x, int y) override;
virtual void click(GUI*, int, int) override;
virtual void mouseMove(GUI*, int x, int y) override;
virtual void doubleClick(int x, int y) override;
virtual void click(int, int) override;
virtual void mouseMove(int x, int y) override;
virtual bool isFocuskeeper() const override {return true;}
virtual void draw(const DrawContext& pctx, const Assets& assets) override;
virtual void drawBackground(const DrawContext& pctx, const Assets& assets) override;
+5 -4
View File
@@ -9,12 +9,13 @@
using namespace gui;
TrackBar::TrackBar(
GUI& gui,
double min,
double max,
double value,
double step,
int trackWidth
) : UINode(glm::vec2(26)),
) : UINode(gui, glm::vec2(26)),
min(min),
max(max),
value(value),
@@ -54,7 +55,7 @@ void TrackBar::setSubConsumer(doubleconsumer consumer) {
this->subconsumer = std::move(consumer);
}
void TrackBar::mouseMove(GUI*, int x, int) {
void TrackBar::mouseMove(int x, int) {
glm::vec2 pos = calcPos();
value = x - trackWidth/2;
value -= pos.x;
@@ -62,7 +63,7 @@ void TrackBar::mouseMove(GUI*, int x, int) {
value += min;
value = (value > max) ? max : value;
value = (value < min) ? min : value;
value = (int64_t)round(value / step) * step;
value = static_cast<int64_t>(std::round(value / step)) * step;
if (consumer && !changeOnRelease) {
consumer(value);
@@ -72,7 +73,7 @@ void TrackBar::mouseMove(GUI*, int x, int) {
}
}
void TrackBar::mouseRelease(GUI*, int, int) {
void TrackBar::mouseRelease(int, int) {
if (consumer && changeOnRelease) {
consumer(value);
}
+10 -7
View File
@@ -16,19 +16,22 @@ namespace gui {
int trackWidth;
bool changeOnRelease = false;
public:
TrackBar(double min,
double max,
double value,
double step=1.0,
int trackWidth=12);
TrackBar(
GUI& gui,
double min,
double max,
double value,
double step = 1.0,
int trackWidth = 12
);
virtual void draw(const DrawContext& pctx, const Assets& assets) override;
virtual void setSupplier(doublesupplier);
virtual void setConsumer(doubleconsumer);
virtual void setSubConsumer(doubleconsumer);
virtual void mouseMove(GUI*, int x, int y) override;
virtual void mouseRelease(GUI*, int x, int y) override;
virtual void mouseMove(int x, int y) override;
virtual void mouseRelease(int x, int y) override;
virtual double getValue() const;
virtual double getMin() const;
+4 -4
View File
@@ -8,7 +8,7 @@
using gui::UINode;
using gui::Align;
UINode::UINode(glm::vec2 size) : size(size) {
UINode::UINode(GUI& gui, glm::vec2 size) : gui(gui), size(size) {
}
UINode::~UINode() {
@@ -74,18 +74,18 @@ UINode* UINode::listenDoubleClick(const onaction& action) {
return this;
}
void UINode::click(GUI*, int, int) {
void UINode::click(int, int) {
pressed = true;
}
void UINode::doubleClick(GUI* gui, int x, int y) {
void UINode::doubleClick(int x, int y) {
pressed = true;
if (isInside(glm::vec2(x, y))) {
doubleClickCallbacks.notify(gui);
}
}
void UINode::mouseRelease(GUI* gui, int x, int y) {
void UINode::mouseRelease(int x, int y) {
pressed = false;
if (isInside(glm::vec2(x, y))) {
actions.notify(gui);
+13 -10
View File
@@ -19,8 +19,8 @@ namespace gui {
class GUI;
class Container;
using onaction = std::function<void(GUI*)>;
using onnumberchange = std::function<void(GUI*, double)>;
using onaction = std::function<void(GUI&)>;
using onnumberchange = std::function<void(GUI&, double)>;
class ActionsSet {
std::unique_ptr<std::vector<onaction>> callbacks;
@@ -32,7 +32,7 @@ namespace gui {
callbacks->push_back(callback);
}
void notify(GUI* gui) {
void notify(GUI& gui) {
if (callbacks) {
for (auto& callback : *callbacks) {
callback(gui);
@@ -64,6 +64,9 @@ namespace gui {
/// @brief Base abstract class for all UI elements
class UINode : public std::enable_shared_from_this<UINode> {
protected:
GUI& gui;
private:
/// @brief element identifier used for direct access in UiDocument
std::string id = "";
/// @brief element enabled state
@@ -118,7 +121,7 @@ namespace gui {
/// @brief cursor shape when mouse is over the element
CursorShape cursor = CursorShape::ARROW;
UINode(glm::vec2 size);
UINode(GUI& gui, glm::vec2 size);
public:
virtual ~UINode();
@@ -169,12 +172,12 @@ namespace gui {
virtual UINode* listenAction(const onaction &action);
virtual UINode* listenDoubleClick(const onaction &action);
virtual void onFocus(GUI*) {focused = true;}
virtual void doubleClick(GUI*, int x, int y);
virtual void click(GUI*, int x, int y);
virtual void clicked(GUI*, mousecode button) {}
virtual void mouseMove(GUI*, int x, int y) {};
virtual void mouseRelease(GUI*, int x, int y);
virtual void onFocus() {focused = true;}
virtual void doubleClick(int x, int y);
virtual void click(int x, int y);
virtual void clicked(mousecode button) {}
virtual void mouseMove(int x, int y) {};
virtual void mouseRelease(int x, int y);
virtual void scrolled(int value);
bool isPressed() const;