Added some scroll area and grid fixes
This commit is contained in:
parent
886fd313a4
commit
0853df4d2a
7 changed files with 224 additions and 23 deletions
|
|
@ -125,7 +125,7 @@ void GUIHolder::draw(SkCanvas* canvas, bool skiaAA) {
|
|||
gui.io.redrawSurface = true;
|
||||
}
|
||||
|
||||
gui.draw(canvas, skiaAA);
|
||||
gui.draw_force(canvas, skiaAA);
|
||||
}
|
||||
|
||||
void GUIHolder::input_paste_callback(const CustomEvents::PasteEvent& paste) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#include "ScrollAreaHelpers.hpp"
|
||||
#include "../GUIManager.hpp"
|
||||
#include "../Elements/LayoutElement.hpp"
|
||||
|
||||
namespace GUIStuff { namespace ElementHelpers {
|
||||
|
||||
|
|
@ -15,6 +16,7 @@ ScrollArea* scroll_area_many_entries(GUIManager& gui, const char* id, const Scro
|
|||
float absScrollAmount = std::fabs(params.scrollOffset->y());
|
||||
size_t startPoint = absScrollAmount / options.entryHeight;
|
||||
size_t elementsContainable = (params.containerDimensions.y() / options.entryHeight) + 2; // Displaying 2 more elements ensures that there isn't any empty space in the container
|
||||
elementsContainable = std::min<size_t>(elementsContainable, 100);
|
||||
size_t endPoint = std::min(options.entryCount, startPoint + elementsContainable);
|
||||
|
||||
if(startPoint != 0) {
|
||||
|
|
@ -25,8 +27,19 @@ ScrollArea* scroll_area_many_entries(GUIManager& gui, const char* id, const Scro
|
|||
}) { }
|
||||
}
|
||||
|
||||
for(size_t i = startPoint; i < endPoint; i++)
|
||||
gui.new_id(i, [&] { options.elementContent(i); });
|
||||
gui.new_id("many element list", [&] {
|
||||
for(size_t i = startPoint; i < endPoint; i++) {
|
||||
gui.new_id(i, [&] {
|
||||
gui.element<LayoutElement>("elem", [&] (LayoutElement*, const Clay_ElementId& lId) {
|
||||
CLAY(lId, {
|
||||
.layout = { .sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIXED(options.entryHeight)}}
|
||||
}) {
|
||||
options.elementContent(i);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
if(endPoint != options.entryCount) {
|
||||
CLAY_AUTO_ID({
|
||||
|
|
|
|||
|
|
@ -7,9 +7,11 @@ namespace GUIStuff {
|
|||
|
||||
GridScrollArea::GridScrollArea(GUIManager& gui): Element(gui) {}
|
||||
|
||||
void GridScrollArea::layout(const Clay_ElementId& id, const Options& options) {
|
||||
void GridScrollArea::layout(const Clay_ElementId& id, const Options& o) {
|
||||
using namespace ElementHelpers;
|
||||
|
||||
options = o;
|
||||
|
||||
ScrollBarManyEntriesOptions opts;
|
||||
opts.clipHorizontal = true;
|
||||
opts.entryHeight = options.entryHeight;
|
||||
|
|
@ -18,29 +20,36 @@ void GridScrollArea::layout(const Clay_ElementId& id, const Options& options) {
|
|||
if(extraCallback) extraCallback(contParams);
|
||||
};
|
||||
size_t entriesPerRow = static_cast<size_t>(rowWidth / options.entryMaximumWidth) + 1;
|
||||
size_t rowCount = options.entryCount / entriesPerRow;
|
||||
size_t rowCount = (options.entryCount + entriesPerRow - 1) / entriesPerRow;
|
||||
float entryWidth = rowWidth == 0.0f ? 100.0f : (rowWidth / entriesPerRow);
|
||||
opts.entryCount = rowCount;
|
||||
opts.elementContent = [&] (size_t rowIndex) {
|
||||
CLAY_AUTO_ID({
|
||||
.layout = {
|
||||
.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIXED(options.entryHeight)},
|
||||
.childAlignment = { .x = options.childAlignmentX}
|
||||
gui.new_id("grid row", [&] {
|
||||
CLAY_AUTO_ID({
|
||||
.layout = {
|
||||
.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIXED(options.entryHeight)},
|
||||
.childAlignment = { .x = options.childAlignmentX}
|
||||
}
|
||||
}) {
|
||||
size_t startIndex = rowIndex * entriesPerRow;
|
||||
size_t endIndex = std::min(rowIndex * entriesPerRow + entriesPerRow, o.entryCount);
|
||||
for(size_t i = startIndex; i < endIndex; i++) {
|
||||
gui.new_id(static_cast<int64_t>(i), [&] {
|
||||
CLAY_AUTO_ID({
|
||||
.layout = {.sizing = {.width = CLAY_SIZING_FIXED(entryWidth), .height = CLAY_SIZING_FIXED(options.entryHeight)}}
|
||||
}) {
|
||||
options.elementContent(i);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}) {
|
||||
for(size_t i = 0; i < entriesPerRow; i++) {
|
||||
size_t entryNum = rowIndex * entriesPerRow + i;
|
||||
gui.new_id(static_cast<int64_t>(i), [&] {
|
||||
CLAY_AUTO_ID({
|
||||
.layout = {.sizing = {.width = CLAY_SIZING_FIXED(entryWidth), .height = CLAY_SIZING_FIXED(options.entryHeight)}}
|
||||
}) {
|
||||
options.elementContent(entryNum);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
scroll_area_many_entries(gui, "scroll many area", opts);
|
||||
CLAY(id, {
|
||||
.layout = {.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0)}}
|
||||
}) {
|
||||
scroll_area_many_entries(gui, "scroll many area", opts);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ class GridScrollArea : public Element {
|
|||
|
||||
void layout(const Clay_ElementId& id, const Options& options);
|
||||
private:
|
||||
Options options;
|
||||
float rowWidth = 0.0f;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -294,6 +294,174 @@ void GUIManager::draw(SkCanvas* c, bool skiaAA) {
|
|||
c->drawImage(io.surface->makeTemporaryImage(), 0, 0, {SkFilterMode::kNearest, SkMipmapMode::kNone}, nullptr);
|
||||
}
|
||||
|
||||
void GUIManager::draw_force(SkCanvas* canvas, bool skiaAA) {
|
||||
canvas->save();
|
||||
canvas->scale(io.guiScaleMultiplier, io.guiScaleMultiplier);
|
||||
canvas->translate(io.windowPos.x(), io.windowPos.y());
|
||||
|
||||
for(size_t i = 0; i < static_cast<size_t>(renderCommands.length); i++) {
|
||||
Clay_RenderCommand* command = Clay_RenderCommandArray_Get(&renderCommands, i);
|
||||
Clay_BoundingBox bb = command->boundingBox;
|
||||
|
||||
switch(command->commandType) {
|
||||
case CLAY_RENDER_COMMAND_TYPE_RECTANGLE: {
|
||||
Clay_RectangleRenderData* config = &command->renderData.rectangle;
|
||||
SkVector radii[4] = {
|
||||
{config->cornerRadius.topLeft, config->cornerRadius.topLeft},
|
||||
{config->cornerRadius.topRight, config->cornerRadius.topRight},
|
||||
{config->cornerRadius.bottomRight, config->cornerRadius.bottomRight},
|
||||
{config->cornerRadius.bottomLeft, config->cornerRadius.bottomLeft}
|
||||
};
|
||||
|
||||
SkRRect rrect;
|
||||
rrect.setRectRadii(
|
||||
SkRect::MakeXYWH(bb.x, bb.y, bb.width, bb.height),
|
||||
radii
|
||||
);
|
||||
|
||||
SkPaint paint;
|
||||
paint.setAntiAlias(skiaAA);
|
||||
paint.setStyle(SkPaint::kFill_Style);
|
||||
paint.setColor4f(convert_vec4<SkColor4f>(config->backgroundColor));
|
||||
canvas->drawRRect(rrect, paint);
|
||||
|
||||
break;
|
||||
}
|
||||
case CLAY_RENDER_COMMAND_TYPE_TEXT: {
|
||||
Clay_TextRenderData* config = &command->renderData.text;
|
||||
|
||||
skia::textlayout::ParagraphStyle pStyle;
|
||||
pStyle.setTextAlign(skia::textlayout::TextAlign::kLeft);
|
||||
skia::textlayout::TextStyle tStyle;
|
||||
tStyle.setFontSize(config->fontSize);
|
||||
tStyle.setFontFamilies(io.fonts->get_default_font_families());
|
||||
tStyle.setColor(convert_vec4<SkColor4f>(config->textColor).toSkColor());
|
||||
pStyle.setTextStyle(tStyle);
|
||||
|
||||
skia::textlayout::ParagraphBuilderImpl a(pStyle, io.fonts->collection, SkUnicodes::ICU::Make());
|
||||
a.addText(config->stringContents.chars, config->stringContents.length);
|
||||
std::unique_ptr<skia::textlayout::Paragraph> p = a.Build();
|
||||
p->layout(std::numeric_limits<float>::max());
|
||||
p->paint(canvas, bb.x, bb.y);
|
||||
|
||||
break;
|
||||
}
|
||||
case CLAY_RENDER_COMMAND_TYPE_BORDER: {
|
||||
Clay_BorderRenderData* config = &command->renderData.border;
|
||||
|
||||
SkPaint p;
|
||||
p.setColor4f(convert_vec4<SkColor4f>(config->color));
|
||||
p.setStyle(SkPaint::kStroke_Style);
|
||||
p.setAntiAlias(skiaAA);
|
||||
|
||||
float halfLineWidth = 0.0f;
|
||||
// Top Left corner
|
||||
if (config->cornerRadius.topLeft > 0.0f) {
|
||||
SkPathBuilder path;
|
||||
float lineWidth = config->width.top;
|
||||
p.setStrokeWidth(lineWidth);
|
||||
path.moveTo(bb.x + halfLineWidth, bb.y + config->cornerRadius.topLeft + halfLineWidth);
|
||||
path.arcTo(SkPoint{(bb.x + halfLineWidth), (bb.y + halfLineWidth)}, SkPoint{(bb.x + config->cornerRadius.topLeft + halfLineWidth), (bb.y + halfLineWidth)}, config->cornerRadius.topLeft);
|
||||
canvas->drawPath(path.detach(), p);
|
||||
}
|
||||
// Top border
|
||||
if (config->width.top > 0.0f) {
|
||||
SkPathBuilder path;
|
||||
float lineWidth = config->width.top;
|
||||
p.setStrokeWidth(lineWidth);
|
||||
path.moveTo((bb.x + config->cornerRadius.topLeft + halfLineWidth), (bb.y + halfLineWidth));
|
||||
path.lineTo((bb.x + bb.width - config->cornerRadius.topRight - halfLineWidth), (bb.y + halfLineWidth));
|
||||
canvas->drawPath(path.detach(), p);
|
||||
}
|
||||
// Top Right Corner
|
||||
if (config->cornerRadius.topRight > 0.0f) {
|
||||
SkPathBuilder path;
|
||||
float lineWidth = config->width.top;
|
||||
p.setStrokeWidth(lineWidth);
|
||||
path.moveTo((bb.x + bb.width - config->cornerRadius.topRight - halfLineWidth), (bb.y + halfLineWidth));
|
||||
path.arcTo(SkPoint{(bb.x + bb.width - halfLineWidth), (bb.y + halfLineWidth)}, SkPoint{(bb.x + bb.width - halfLineWidth), (bb.y + config->cornerRadius.topRight + halfLineWidth)}, config->cornerRadius.topRight);
|
||||
canvas->drawPath(path.detach(), p);
|
||||
}
|
||||
// Right border
|
||||
if (config->width.right > 0.0f) {
|
||||
SkPathBuilder path;
|
||||
float lineWidth = config->width.right;
|
||||
p.setStrokeWidth(lineWidth);
|
||||
path.moveTo((bb.x + bb.width - halfLineWidth), (bb.y + config->cornerRadius.topRight + halfLineWidth));
|
||||
path.lineTo((bb.x + bb.width - halfLineWidth), (bb.y + bb.height - config->cornerRadius.bottomRight - halfLineWidth));
|
||||
canvas->drawPath(path.detach(), p);
|
||||
}
|
||||
// Bottom Right Corner
|
||||
if (config->cornerRadius.bottomRight > 0.0f) {
|
||||
SkPathBuilder path;
|
||||
float lineWidth = config->width.bottom;
|
||||
p.setStrokeWidth(lineWidth);
|
||||
path.moveTo((bb.x + bb.width - halfLineWidth), (bb.y + bb.height - config->cornerRadius.bottomRight - halfLineWidth));
|
||||
path.arcTo(SkPoint{(bb.x + bb.width - halfLineWidth), (bb.y + bb.height - halfLineWidth)}, SkPoint{(bb.x + bb.width - config->cornerRadius.bottomRight - halfLineWidth), (bb.y + bb.height - halfLineWidth)}, config->cornerRadius.bottomRight);
|
||||
canvas->drawPath(path.detach(), p);
|
||||
}
|
||||
// Bottom Border
|
||||
if (config->width.bottom > 0.0f) {
|
||||
SkPathBuilder path;
|
||||
float lineWidth = config->width.bottom;
|
||||
p.setStrokeWidth(lineWidth);
|
||||
path.moveTo((bb.x + config->cornerRadius.bottomLeft + halfLineWidth), (bb.y + bb.height - halfLineWidth));
|
||||
path.lineTo((bb.x + bb.width - config->cornerRadius.bottomRight - halfLineWidth), (bb.y + bb.height - halfLineWidth));
|
||||
canvas->drawPath(path.detach(), p);
|
||||
}
|
||||
// Bottom Left Corner
|
||||
if (config->cornerRadius.bottomLeft > 0.0f) {
|
||||
SkPathBuilder path;
|
||||
float lineWidth = config->width.bottom;
|
||||
p.setStrokeWidth(lineWidth);
|
||||
path.moveTo((bb.x + config->cornerRadius.bottomLeft + halfLineWidth), (bb.y + bb.height - halfLineWidth));
|
||||
path.arcTo(SkPoint{(bb.x + halfLineWidth), (bb.y + bb.height - halfLineWidth)}, SkPoint{(bb.x + halfLineWidth), (bb.y + bb.height - config->cornerRadius.bottomLeft - halfLineWidth)}, config->cornerRadius.bottomLeft);
|
||||
canvas->drawPath(path.detach(), p);
|
||||
}
|
||||
// Left Border
|
||||
if (config->width.left > 0.0f) {
|
||||
SkPathBuilder path;
|
||||
float lineWidth = config->width.left;
|
||||
p.setStrokeWidth(lineWidth);
|
||||
path.moveTo((bb.x + halfLineWidth), (bb.y + bb.height - config->cornerRadius.bottomLeft - halfLineWidth));
|
||||
path.lineTo((bb.x + halfLineWidth), (bb.y + config->cornerRadius.topRight + halfLineWidth));
|
||||
canvas->drawPath(path.detach(), p);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CLAY_RENDER_COMMAND_TYPE_SCISSOR_START: {
|
||||
Clay_ClipRenderData* clip = &command->renderData.clip;
|
||||
if(!clip->horizontal) {
|
||||
bb.x = 0.0f;
|
||||
bb.width = std::numeric_limits<float>::max();
|
||||
}
|
||||
if(!clip->vertical) {
|
||||
bb.y = 0.0f;
|
||||
bb.height = std::numeric_limits<float>::max();
|
||||
}
|
||||
|
||||
canvas->save();
|
||||
SkRect clipRect = SkRect::MakeXYWH(bb.x - 1.0f, bb.y - 1.0f, bb.width + 1.0f, bb.height + 1.0f);
|
||||
canvas->clipRect(clipRect);
|
||||
break;
|
||||
}
|
||||
case CLAY_RENDER_COMMAND_TYPE_SCISSOR_END: {
|
||||
canvas->restore();
|
||||
break;
|
||||
}
|
||||
case CLAY_RENDER_COMMAND_TYPE_CUSTOM: {
|
||||
Element* customElement = static_cast<Element*>(command->renderData.custom.customData);
|
||||
customElement->clay_draw(canvas, io, command, skiaAA);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
canvas->restore();
|
||||
}
|
||||
|
||||
SCollision::AABB<float> GUIManager::get_invalid_draw_bb_from_command(const Clay_RenderCommand* command) {
|
||||
BorderData extraPadding;
|
||||
if(command->commandType == CLAY_RENDER_COMMAND_TYPE_BORDER) {
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ class GUIManager {
|
|||
|
||||
GUIManager();
|
||||
void draw(SkCanvas* c, bool skiaAA);
|
||||
void draw_force(SkCanvas* canvas, bool skiaAA);
|
||||
void set_to_layout();
|
||||
void layout_if_necessary();
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#include "Helpers/ConvertVec.hpp"
|
||||
#include "../GUIStuff/Elements/GridScrollArea.hpp"
|
||||
#include "../GUIStuff/ElementHelpers/ButtonHelpers.hpp"
|
||||
#include "../GUIStuff/ElementHelpers/ScrollAreaHelpers.hpp"
|
||||
|
||||
FileSelectScreen::FileSelectScreen(MainProgram& m): Screen(m) {}
|
||||
|
||||
|
|
@ -22,11 +23,19 @@ void FileSelectScreen::gui_layout_run() {
|
|||
},
|
||||
}) {
|
||||
text_label(gui, "Test grid");
|
||||
//scroll_area_many_entries(gui, "Test scroll", ScrollBarManyEntriesOptions{
|
||||
// .entryHeight = 100.0f,
|
||||
// .entryCount = 2000,
|
||||
// .clipHorizontal = true,
|
||||
// .elementContent = [&] (size_t i) {
|
||||
// text_button_sized(gui, "button", "Square " + std::to_string(i), CLAY_SIZING_GROW(0), CLAY_SIZING_GROW(0));
|
||||
// }
|
||||
//});
|
||||
gui.element<GridScrollArea>("Test grid", GridScrollArea::Options{
|
||||
.entryMaximumWidth = 100.0f,
|
||||
.childAlignmentX = CLAY_ALIGN_X_LEFT,
|
||||
.entryHeight = 100.0f,
|
||||
.entryCount = 700,
|
||||
.entryCount = 200,
|
||||
.elementContent = [&](size_t i) {
|
||||
CLAY_AUTO_ID({
|
||||
.layout = {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue