Added X scrollbar to scroll area, and added toolbar for phone drawing program

This commit is contained in:
Yousef Khadadeh 2026-04-29 15:14:13 +03:00
parent 6a05026f85
commit 74bc17f570
11 changed files with 284 additions and 50 deletions

View file

@ -398,6 +398,36 @@ void DrawingProgram::toolbar_gui(Toolbar& t) {
});
}
void DrawingProgram::phone_bottom_toolbar_gui(PhoneDrawingProgramScreen& t) {
using namespace GUIStuff;
using namespace ElementHelpers;
GUIManager& gui = world.main.g.gui;
auto tool_button = [&](const char* id, const std::string& svgPath, DrawingProgramToolType toolType) {
svg_icon_button(gui, id, svgPath, {
.drawType = SelectableButton::DrawType::TRANSPARENT_ALL,
.isSelected = drawTool->get_type() == toolType,
.onClick = [&, toolType] {
switch_to_tool(toolType);
}
});
};
tool_button("Brush Toolbar Button", "data/icons/brush.svg", DrawingProgramToolType::BRUSH);
tool_button("Eraser Toolbar Button", "data/icons/eraser.svg", DrawingProgramToolType::ERASER);
tool_button("Line Toolbar Button", "data/icons/line.svg", DrawingProgramToolType::LINE);
tool_button("Text Toolbar Button", "data/icons/text.svg", DrawingProgramToolType::TEXTBOX);
tool_button("Ellipse Toolbar Button", "data/icons/circle.svg", DrawingProgramToolType::ELLIPSE);
tool_button("Rect Toolbar Button", "data/icons/rectangle.svg", DrawingProgramToolType::RECTANGLE);
tool_button("RectSelect Toolbar Button", "data/icons/rectselect.svg", DrawingProgramToolType::RECTSELECT);
tool_button("LassoSelect Toolbar Button", "data/icons/lassoselect.svg", DrawingProgramToolType::LASSOSELECT);
tool_button("Edit Toolbar Button", "data/icons/cursor.svg", DrawingProgramToolType::EDIT);
tool_button("Eyedropper Toolbar Button", "data/icons/eyedropper.svg", DrawingProgramToolType::EYEDROPPER);
tool_button("Zoom Canvas Toolbar Button", "data/icons/zoom.svg", DrawingProgramToolType::ZOOM);
tool_button("Pan Canvas Toolbar Button", "data/icons/hand.svg", DrawingProgramToolType::PAN);
}
void DrawingProgram::right_click_popup_gui(Toolbar& t) {
if(rightClickPopupLocation.has_value())
drawTool->right_click_popup_gui(t, rightClickPopupLocation.value());

View file

@ -20,6 +20,7 @@
#include "DrawingProgramSelection.hpp"
class World;
class PhoneDrawingProgramScreen;
class DrawingProgram {
public:
@ -28,6 +29,7 @@ class DrawingProgram {
void toolbar_gui(Toolbar& t);
void tool_options_gui(Toolbar& t);
void right_click_popup_gui(Toolbar& t);
void phone_bottom_toolbar_gui(PhoneDrawingProgramScreen& t);
void update();
void scale_up(const WorldScalar& scaleUpAmount);
void draw(SkCanvas* canvas, const DrawData& drawData);

View file

@ -9,7 +9,7 @@ ScrollArea* scroll_area_many_entries(GUIManager& gui, const char* id, const Scro
.scrollVertical = true,
.clipHorizontal = options.clipHorizontal,
.clipVertical = true,
.showScrollbarY = true,
.scrollbarY = options.scrollbar,
.xAlign = options.xAlign,
.yAlign = CLAY_ALIGN_Y_TOP,
.innerContent = [&](const ScrollArea::InnerContentParameters& params) {

View file

@ -11,6 +11,7 @@ struct ScrollBarManyEntriesOptions {
bool growing = false; // If set to false, this element has a fixed size. Otherwise, is a growing element.
Clay_LayoutAlignmentX xAlign = CLAY_ALIGN_X_LEFT;
Clay_SizingAxis xElementSize = CLAY_SIZING_GROW(0);
ScrollArea::ScrollbarType scrollbar = ScrollArea::ScrollbarType::NORMAL;
std::function<void(size_t elementIndex)> elementContent;
std::function<void(const ScrollArea::InnerContentParameters&)> innerContentExtraCallback;
};

View file

@ -24,6 +24,7 @@ void GridScrollArea::layout(const Clay_ElementId& id, const Options& o) {
size_t entriesPerRow = std::max<size_t>(rowWidth / options.entryWidth, 1);
size_t rowCount = (options.entryCount + entriesPerRow - 1) / entriesPerRow;
opts.entryCount = rowCount;
opts.scrollbar = options.scrollbar;
uint16_t xPadding = 0;
uint16_t xChildGap = 0;

View file

@ -15,6 +15,7 @@ class GridScrollArea : public Element {
float entryHeight;
size_t entryCount;
bool entryWidthIsMinimum = false;
ScrollArea::ScrollbarType scrollbar = ScrollArea::ScrollbarType::NORMAL;
std::function<void(size_t elementIndex)> elementContent;
std::function<void(const ScrollArea::InnerContentParameters&)> innerContentExtraCallback;
};

View file

@ -2,13 +2,13 @@
#include "../GUIManager.hpp"
#include <Helpers/ConvertVec.hpp>
#include <Helpers/Logger.hpp>
#include "Helpers/MathExtras.hpp"
#include "LayoutElement.hpp"
namespace GUIStuff {
constexpr float TOUCH_SCROLLER_WIDTH = 24.0f;
constexpr float DESKTOP_SCROLLER_WIDTH = 12.0f;
constexpr float SCROLL_WHEEL_SCROLL_SPEED = 20.0f;
constexpr float SCROLL_DAMPING = 0.15f; // Damping on the scroll area velocity when its scrolling on its own
constexpr float SCROLL_MINIMUM_MOTION = 0.15f; // When the scroll area is scrolling on its own, this is the minimum velocity required for it to continue
constexpr float SCROLL_MAX_DAMPING = 0.0001f; // Damping on the scrollAreaMotionMax variable
@ -33,7 +33,7 @@ void ScrollArea::layout(const Clay_ElementId& id, const Options& options) {
auto& bb = boundingBox.value();
clamp_scroll();
if(contentDimensions.y() > bb.height()) {
if((contentDimensions.y() > bb.height() && opts.scrollVertical) || (contentDimensions.x() > bb.width() && opts.scrollHorizontal)) {
gui.in_dynamic_area([&] {
opts.innerContent({.contentDimensions = contentDimensions, .containerDimensions = bb.dim(), .scrollOffset = &scrollOffset});
});
@ -43,8 +43,19 @@ void ScrollArea::layout(const Clay_ElementId& id, const Options& options) {
clamp_scroll();
if(contentDimensions.y() > bb.height() && opts.showScrollbarY)
if(contentDimensions.y() > bb.height() && opts.scrollVertical && opts.scrollbarY != ScrollbarType::NONE)
y_scroll_bar();
else {
yScrollbar.scroller = nullptr;
yScrollbar.scrollbar = nullptr;
}
if(contentDimensions.x() > bb.width() && opts.scrollHorizontal && opts.scrollbarX != ScrollbarType::NONE)
x_scroll_bar();
else {
xScrollbar.scroller = nullptr;
xScrollbar.scrollbar = nullptr;
}
}
}
}
@ -59,7 +70,7 @@ void ScrollArea::y_scroll_bar() {
float areaAboveScrollerSize = scrollerPos * (sAreaDim - scrollerSize);
gui.set_z_index(gui.get_z_index() + 1, [&] {
gui.element<LayoutElement>("y scroll bar", [&] (LayoutElement*, const Clay_ElementId& lId) {
yScrollbar.scrollbar = gui.element<LayoutElement>("y scroll bar", [&] (LayoutElement*, const Clay_ElementId& lId) {
CLAY(lId, {
.layout = {
.sizing = {.width = CLAY_SIZING_FIXED(gui.io.isTouchDevice ? TOUCH_SCROLLER_WIDTH : DESKTOP_SCROLLER_WIDTH), .height = CLAY_SIZING_GROW(0)},
@ -76,9 +87,9 @@ void ScrollArea::y_scroll_bar() {
}
}) {
SkColor4f scrollerColor;
if(isScrollbarHeldY)
if(yScrollbar.isScrollbarHeld)
scrollerColor = gui.io.theme->fillColor1;
else if(isScrollbarHoveredY)
else if(yScrollbar.isScrollbarHovered)
scrollerColor = gui.io.theme->fillColor1;
else
scrollerColor = gui.io.theme->fillColor2;
@ -89,7 +100,7 @@ void ScrollArea::y_scroll_bar() {
}
}) {}
scrollerY = gui.element<LayoutElement>("scroller", [&] (LayoutElement*, const Clay_ElementId& lId2) {
yScrollbar.scroller = gui.element<LayoutElement>("scroller", [&] (LayoutElement*, const Clay_ElementId& lId2) {
CLAY(lId2, {
.layout = {
.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIXED(scrollerSize)},
@ -101,7 +112,7 @@ void ScrollArea::y_scroll_bar() {
.layout = {.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0)}}
}) {}
float scrollerWidthPercent = 0.0f;
bool highlighted = isHoveringOverScrollerY || isScrollbarHeldY;
bool highlighted = yScrollbar.isHoveringOverScroller || yScrollbar.isScrollbarHeld || (!gui.io.isTouchDevice && yScrollbar.isScrollbarHovered);
if(gui.io.isTouchDevice)
scrollerWidthPercent = highlighted ? 0.6f : 0.2f;
else
@ -118,55 +129,55 @@ void ScrollArea::y_scroll_bar() {
}
}, LayoutElement::Callbacks{
.onClick = [&, scrollPosMax, sAreaStart, sAreaDim, scrollerSize, areaAboveScrollerSize](LayoutElement* t, const InputManager::MouseButtonCallbackArgs& button) {
bool newIsHoveringOverScrollerY = scrollerY->mouseHovering && (button.deviceType != InputManager::MouseDeviceType::TOUCH || button.down);
bool newIsScrollbarHoveredY = t->mouseHovering && (button.deviceType != InputManager::MouseDeviceType::TOUCH || button.down);
if(isHoveringOverScrollerY != newIsHoveringOverScrollerY) {
isHoveringOverScrollerY = newIsHoveringOverScrollerY;
bool newIsHoveringOverScroller = yScrollbar.scroller->mouseHovering && (button.deviceType != InputManager::MouseDeviceType::TOUCH || button.down);
bool newIsScrollbarHovered = t->mouseHovering && (button.deviceType != InputManager::MouseDeviceType::TOUCH || button.down);
if(yScrollbar.isHoveringOverScroller != newIsHoveringOverScroller) {
yScrollbar.isHoveringOverScroller = newIsHoveringOverScroller;
gui.set_to_layout();
}
if(isScrollbarHoveredY != newIsScrollbarHoveredY) {
isScrollbarHoveredY = newIsScrollbarHoveredY;
if(yScrollbar.isScrollbarHovered != newIsScrollbarHovered) {
yScrollbar.isScrollbarHovered = newIsScrollbarHovered;
gui.set_to_layout();
}
if(button.button == InputManager::MouseButton::LEFT) {
if(button.down && isScrollbarHoveredY) {
isScrollbarHeldY = true;
if(isHoveringOverScrollerY)
scrollerStartPosY = sAreaStart + areaAboveScrollerSize + scrollerSize * 0.5f;
if(button.down && yScrollbar.isScrollbarHovered) {
yScrollbar.isScrollbarHeld = true;
if(yScrollbar.isHoveringOverScroller)
yScrollbar.scrollerStartPos = sAreaStart + areaAboveScrollerSize + scrollerSize * 0.5f;
else
scrollerStartPosY = std::clamp(button.pos.y(), sAreaStart + scrollerSize * 0.5f, sAreaStart + sAreaDim - scrollerSize * 0.5f);
mouseStartPosY = button.pos.y();
yScrollbar.scrollerStartPos = std::clamp(button.pos.y(), sAreaStart + scrollerSize * 0.5f, sAreaStart + sAreaDim - scrollerSize * 0.5f);
yScrollbar.mouseStartPos = button.pos.y();
float newScrollPosFrac;
newScrollPosFrac = std::clamp((scrollerStartPosY - (mouseStartPosY - button.pos.y()) - sAreaStart - scrollerSize * 0.5f) / (sAreaDim - scrollerSize), 0.0f, 1.0f);
newScrollPosFrac = std::clamp((yScrollbar.scrollerStartPos - (yScrollbar.mouseStartPos - button.pos.y()) - sAreaStart - scrollerSize * 0.5f) / (sAreaDim - scrollerSize), 0.0f, 1.0f);
scrollOffset.y() = newScrollPosFrac * (-scrollPosMax);
clamp_scroll();
scrollAreaMotionMax = scrollAreaMotion = {0.0f, 0.0f};
gui.set_to_layout();
}
else if(isScrollbarHeldY) {
isScrollbarHeldY = false;
else if(yScrollbar.isScrollbarHeld) {
yScrollbar.isScrollbarHeld = false;
scrollAreaMotionMax = scrollAreaMotion = {0.0f, 0.0f};
gui.set_to_layout();
}
}
},
.onMotion = [&, scrollPosMax, sAreaStart, sAreaDim, scrollerSize](LayoutElement* t, const InputManager::MouseMotionCallbackArgs& motion) {
bool newIsHoveringOverScrollerY = scrollerY->mouseHovering && motion.deviceType != InputManager::MouseDeviceType::TOUCH;
bool newIsScrollbarHoveredY = t->mouseHovering && motion.deviceType != InputManager::MouseDeviceType::TOUCH;
if(isHoveringOverScrollerY != newIsHoveringOverScrollerY) {
isHoveringOverScrollerY = newIsHoveringOverScrollerY;
bool newIsHoveringOverScroller = yScrollbar.scroller->mouseHovering && motion.deviceType != InputManager::MouseDeviceType::TOUCH;
bool newIsScrollbarHovered = t->mouseHovering && motion.deviceType != InputManager::MouseDeviceType::TOUCH;
if(yScrollbar.isHoveringOverScroller != newIsHoveringOverScroller) {
yScrollbar.isHoveringOverScroller = newIsHoveringOverScroller;
gui.set_to_layout();
}
if(isScrollbarHoveredY != newIsScrollbarHoveredY) {
isScrollbarHoveredY = newIsScrollbarHoveredY;
if(yScrollbar.isScrollbarHovered != newIsScrollbarHovered) {
yScrollbar.isScrollbarHovered = newIsScrollbarHovered;
gui.set_to_layout();
}
if(isScrollbarHeldY) {
if(yScrollbar.isScrollbarHeld) {
float oldScrollOffset = scrollOffset.y();
float newScrollPosFrac;
newScrollPosFrac = std::clamp((scrollerStartPosY - (mouseStartPosY - motion.pos.y()) - sAreaStart - scrollerSize * 0.5f) / (sAreaDim - scrollerSize), 0.0f, 1.0f);
newScrollPosFrac = std::clamp((yScrollbar.scrollerStartPos - (yScrollbar.mouseStartPos - motion.pos.y()) - sAreaStart - scrollerSize * 0.5f) / (sAreaDim - scrollerSize), 0.0f, 1.0f);
scrollOffset.y() = newScrollPosFrac * (-scrollPosMax);
clamp_scroll();
scrollAreaMotionMax = scrollAreaMotion = {0.0f, 0.0f};
@ -178,6 +189,135 @@ void ScrollArea::y_scroll_bar() {
});
}
void ScrollArea::x_scroll_bar() {
float sAreaDim = boundingBox.value().width();
float sAreaStart = boundingBox.value().min.x();
float contDim = contentDimensions.x();
float scrollerSize = (sAreaDim / contDim) * sAreaDim;
float scrollPosMax = contDim - sAreaDim;
float scrollerPos = std::fabs(scrollOffset.x() / scrollPosMax);
float areaAboveScrollerSize = scrollerPos * (sAreaDim - scrollerSize);
gui.set_z_index(gui.get_z_index() + 1, [&] {
xScrollbar.scrollbar = gui.element<LayoutElement>("x scroll bar", [&] (LayoutElement*, const Clay_ElementId& lId) {
CLAY(lId, {
.layout = {
.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIXED(gui.io.isTouchDevice ? TOUCH_SCROLLER_WIDTH : DESKTOP_SCROLLER_WIDTH)},
.childAlignment = {.x = CLAY_ALIGN_X_LEFT, .y = CLAY_ALIGN_Y_TOP},
.layoutDirection = CLAY_LEFT_TO_RIGHT
},
.floating = {
.zIndex = gui.get_z_index(),
.attachPoints = {
.element = CLAY_ATTACH_POINT_LEFT_BOTTOM,
.parent = CLAY_ATTACH_POINT_LEFT_BOTTOM
},
.attachTo = CLAY_ATTACH_TO_PARENT,
}
}) {
SkColor4f scrollerColor;
if(xScrollbar.isScrollbarHeld)
scrollerColor = gui.io.theme->fillColor1;
else if(xScrollbar.isScrollbarHovered)
scrollerColor = gui.io.theme->fillColor1;
else
scrollerColor = gui.io.theme->fillColor2;
CLAY_AUTO_ID({
.layout = {
.sizing = {.width = CLAY_SIZING_FIXED(areaAboveScrollerSize), .height = CLAY_SIZING_GROW(0)}
}
}) {}
xScrollbar.scroller = gui.element<LayoutElement>("scroller", [&] (LayoutElement*, const Clay_ElementId& lId2) {
CLAY(lId2, {
.layout = {
.sizing = {.width = CLAY_SIZING_FIXED(scrollerSize), .height = CLAY_SIZING_GROW(0)},
.childAlignment = {.x = CLAY_ALIGN_X_LEFT, .y = CLAY_ALIGN_Y_TOP},
.layoutDirection = CLAY_TOP_TO_BOTTOM,
}
}) {
CLAY_AUTO_ID({
.layout = {.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0)}}
}) {}
float scrollerWidthPercent = 0.0f;
bool highlighted = xScrollbar.isHoveringOverScroller || xScrollbar.isScrollbarHeld || (!gui.io.isTouchDevice && xScrollbar.isScrollbarHovered);
if(gui.io.isTouchDevice)
scrollerWidthPercent = highlighted ? 0.6f : 0.2f;
else
scrollerWidthPercent = highlighted ? 1.0f : 0.5f;
CLAY_AUTO_ID({
.layout = {.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_PERCENT(scrollerWidthPercent)}},
.backgroundColor = convert_vec4<Clay_Color>(highlighted ? gui.io.theme->fillColor1 : gui.io.theme->fillColor2),
.cornerRadius = CLAY_CORNER_RADIUS(3),
}) {}
}
});
CLAY_AUTO_ID({ .layout = {.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0)}}}) {}
}
}, LayoutElement::Callbacks{
.onClick = [&, scrollPosMax, sAreaStart, sAreaDim, scrollerSize, areaAboveScrollerSize](LayoutElement* t, const InputManager::MouseButtonCallbackArgs& button) {
bool newIsHoveringOverScroller = xScrollbar.scroller->mouseHovering && (button.deviceType != InputManager::MouseDeviceType::TOUCH || button.down);
bool newIsScrollbarHovered = t->mouseHovering && (button.deviceType != InputManager::MouseDeviceType::TOUCH || button.down);
if(xScrollbar.isHoveringOverScroller != newIsHoveringOverScroller) {
xScrollbar.isHoveringOverScroller = newIsHoveringOverScroller;
gui.set_to_layout();
}
if(xScrollbar.isScrollbarHovered != newIsScrollbarHovered) {
xScrollbar.isScrollbarHovered = newIsScrollbarHovered;
gui.set_to_layout();
}
if(button.button == InputManager::MouseButton::LEFT) {
if(button.down && xScrollbar.isScrollbarHovered) {
xScrollbar.isScrollbarHeld = true;
if(xScrollbar.isHoveringOverScroller)
xScrollbar.scrollerStartPos = sAreaStart + areaAboveScrollerSize + scrollerSize * 0.5f;
else
xScrollbar.scrollerStartPos = std::clamp(button.pos.x(), sAreaStart + scrollerSize * 0.5f, sAreaStart + sAreaDim - scrollerSize * 0.5f);
xScrollbar.mouseStartPos = button.pos.x();
float newScrollPosFrac;
newScrollPosFrac = std::clamp((xScrollbar.scrollerStartPos - (xScrollbar.mouseStartPos - button.pos.x()) - sAreaStart - scrollerSize * 0.5f) / (sAreaDim - scrollerSize), 0.0f, 1.0f);
scrollOffset.x() = newScrollPosFrac * (-scrollPosMax);
clamp_scroll();
scrollAreaMotionMax = scrollAreaMotion = {0.0f, 0.0f};
gui.set_to_layout();
}
else if(xScrollbar.isScrollbarHeld) {
xScrollbar.isScrollbarHeld = false;
scrollAreaMotionMax = scrollAreaMotion = {0.0f, 0.0f};
gui.set_to_layout();
}
}
},
.onMotion = [&, scrollPosMax, sAreaStart, sAreaDim, scrollerSize](LayoutElement* t, const InputManager::MouseMotionCallbackArgs& motion) {
bool newIsHoveringOverScroller = xScrollbar.scroller->mouseHovering && motion.deviceType != InputManager::MouseDeviceType::TOUCH;
bool newIsScrollbarHovered = t->mouseHovering && motion.deviceType != InputManager::MouseDeviceType::TOUCH;
if(xScrollbar.isHoveringOverScroller != newIsHoveringOverScroller) {
xScrollbar.isHoveringOverScroller = newIsHoveringOverScroller;
gui.set_to_layout();
}
if(xScrollbar.isScrollbarHovered != newIsScrollbarHovered) {
xScrollbar.isScrollbarHovered = newIsScrollbarHovered;
gui.set_to_layout();
}
if(xScrollbar.isScrollbarHeld) {
float oldScrollOffset = scrollOffset.x();
float newScrollPosFrac;
newScrollPosFrac = std::clamp((xScrollbar.scrollerStartPos - (xScrollbar.mouseStartPos - motion.pos.x()) - sAreaStart - scrollerSize * 0.5f) / (sAreaDim - scrollerSize), 0.0f, 1.0f);
scrollOffset.x() = newScrollPosFrac * (-scrollPosMax);
clamp_scroll();
scrollAreaMotionMax = scrollAreaMotion = {0.0f, 0.0f};
if(oldScrollOffset != scrollOffset.x())
gui.set_to_layout();
}
}
});
});
}
void ScrollArea::reset_scroll() {
scrollAreaMotion = scrollAreaMotionMax = scrollOffset = {0.0f, 0.0f};
}
@ -210,13 +350,17 @@ void ScrollArea::update() {
}
void ScrollArea::input_mouse_wheel_callback(const InputManager::MouseWheelCallbackArgs& wheel) {
if(mouseHovering) {
if(mouseHovering || (xScrollbar.scrollbar && xScrollbar.scrollbar->mouseHovering) || (yScrollbar.scrollbar && yScrollbar.scrollbar->mouseHovering)) {
Vector2f oldScrollOffset = scrollOffset;
if(opts.scrollVertical)
scrollOffset.y() = scrollOffset.y() + wheel.amount.y() * 10.0f;
if(opts.scrollHorizontal)
scrollOffset.y() = scrollOffset.x() + wheel.amount.x() * 10.0f;
if(opts.scrollVertical) {
scrollOffset.y() += wheel.amount.y() * SCROLL_WHEEL_SCROLL_SPEED;
if(opts.scrollHorizontal)
scrollOffset.x() += wheel.amount.x() * SCROLL_WHEEL_SCROLL_SPEED;
}
else if(opts.scrollHorizontal)
scrollOffset.x() += wheel.amount.y() * SCROLL_WHEEL_SCROLL_SPEED;
clamp_scroll();
if(oldScrollOffset != scrollOffset)

View file

@ -14,13 +14,19 @@ class ScrollArea : public Element {
Vector2f* scrollOffset;
};
enum class ScrollbarType {
NONE,
NO_INTERACTION,
NORMAL
};
struct Options {
bool scrollVertical = false;
bool scrollHorizontal = false;
bool clipHorizontal = false;
bool clipVertical = false;
bool showScrollbarX = false;
bool showScrollbarY = false;
ScrollbarType scrollbarX = ScrollbarType::NONE;
ScrollbarType scrollbarY = ScrollbarType::NONE;
Clay_LayoutDirection layoutDirection = CLAY_TOP_TO_BOTTOM;
Clay_LayoutAlignmentX xAlign = CLAY_ALIGN_X_LEFT;
Clay_LayoutAlignmentY yAlign = CLAY_ALIGN_Y_TOP;
@ -43,13 +49,21 @@ class ScrollArea : public Element {
Vector2f scrollAreaMotion = {0.0f, 0.0f};
Vector2f scrollAreaMotionMax = {0.0f, 0.0f};
bool isScrollbarHeldY = false;
bool isScrollbarHoveredY = false;
bool isHoveringOverScrollerY = false;
Element* scrollerY = nullptr;
float scrollerStartPosY;
float mouseStartPosY;
struct ScrollbarData {
bool isScrollbarHeld = false;
bool isScrollbarHovered = false;
bool isHoveringOverScroller = false;
Element* scroller = nullptr;
Element* scrollbar = nullptr;
float scrollerStartPos;
float mouseStartPos;
};
ScrollbarData xScrollbar;
ScrollbarData yScrollbar;
void y_scroll_bar();
void x_scroll_bar();
Vector2f contentDimensions = {0.0f, 0.0f};
Vector2f scrollOffset = {0.0f, 0.0f};

View file

@ -31,6 +31,10 @@ void PhoneDrawingProgramScreen::main_display() {
},
}) {
top_toolbar();
CLAY_AUTO_ID({
.layout = {.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0)}}
}) {}
bottom_toolbar();
}
}
@ -66,6 +70,42 @@ void PhoneDrawingProgramScreen::top_toolbar() {
});
}
void PhoneDrawingProgramScreen::bottom_toolbar() {
auto& gui = main.g.gui;
auto& io = gui.io;
auto& drawProg = main.world->drawProg;
window_fill_side_bar(gui, "bottom toolbar", {
.dir = WindowFillSideBarConfig::Direction::BOTTOM,
.backgroundColor = io.theme->backColor1
}, [&] {
CLAY_AUTO_ID({
.layout = {
.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIT(0) },
.childAlignment = { .x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_CENTER},
.layoutDirection = CLAY_LEFT_TO_RIGHT
}
}) {
CLAY_AUTO_ID({
.layout = {
.sizing = {.width = CLAY_SIZING_FIT(0), .height = CLAY_SIZING_FIT(0) }
}
}) {
gui.element<ScrollArea>("tools scroll", ScrollArea::Options{
.scrollHorizontal = true,
.clipHorizontal = true,
.scrollbarX = ScrollArea::ScrollbarType::NONE,
.layoutDirection = CLAY_LEFT_TO_RIGHT,
.xAlign = CLAY_ALIGN_X_LEFT,
.yAlign = CLAY_ALIGN_Y_CENTER,
.innerContent = [&](auto&) {
drawProg.phone_bottom_toolbar_gui(*this);
}
});
}
}
});
}
void PhoneDrawingProgramScreen::input_global_back_button_callback() {
main.world->save_to_file(main.world->filePath);
main.set_tab_to_close(main.world.get());

View file

@ -12,5 +12,6 @@ class PhoneDrawingProgramScreen : public DrawingProgramScreen {
private:
void save_files();
void top_toolbar();
void bottom_toolbar();
void main_display();
};

View file

@ -291,7 +291,7 @@ void Toolbar::close_popup_gui() {
gui.clipping_element<ScrollArea>("close file popup gui scroll area", ScrollArea::Options{
.scrollVertical = true,
.clipVertical = true,
.showScrollbarY = true,
.scrollbarY = ScrollArea::ScrollbarType::NORMAL,
.innerContent = [&](const ScrollArea::InnerContentParameters&) {
CLAY_AUTO_ID({
.layout = {
@ -1236,7 +1236,7 @@ void Toolbar::color_palette(const char* id, Vector4f* color, const std::function
gui.element<ScrollArea>("color palette scroll area", ScrollArea::Options{
.scrollVertical = true,
.clipVertical = true,
.showScrollbarY = true,
.scrollbarY = ScrollArea::ScrollbarType::NORMAL,
.innerContent = [&](const ScrollArea::InnerContentParameters&) {
CLAY_AUTO_ID({
.layout = {
@ -1683,7 +1683,7 @@ void Toolbar::general_settings_inner_gui() {
gui.clipping_element<ScrollArea>("general settings scroll area", ScrollArea::Options{
.scrollVertical = true,
.clipVertical = true,
.showScrollbarY = true,
.scrollbarY = ScrollArea::ScrollbarType::NORMAL,
.innerContent = [&, innerContent](const ScrollArea::InnerContentParameters&) {
CLAY_AUTO_ID({
.layout = {
@ -1911,7 +1911,7 @@ void Toolbar::about_menu_inner_gui() {
gui.clipping_element<ScrollArea>("About Menu Selector Scroll Area", ScrollArea::Options{
.scrollVertical = true,
.clipVertical = true,
.showScrollbarY = true,
.scrollbarY = ScrollArea::ScrollbarType::NORMAL,
.innerContent = [&](const ScrollArea::InnerContentParameters&) {
CLAY_AUTO_ID({
.layout = {
@ -1953,7 +1953,7 @@ void Toolbar::about_menu_inner_gui() {
gui.clipping_element<ScrollArea>("About Menu Text Scroll Area", ScrollArea::Options{
.scrollVertical = true,
.clipVertical = true,
.showScrollbarY = true,
.scrollbarY = ScrollArea::ScrollbarType::NORMAL,
.innerContent = [&](const ScrollArea::InnerContentParameters&) {
text_label_size(gui, (selectedLicense == -1) ? main.conf.ownLicenseText : main.conf.thirdPartyLicenses[selectedLicense].second, 0.8f);
}