diff --git a/src/DrawingProgram/DrawingProgram.cpp b/src/DrawingProgram/DrawingProgram.cpp index 511fa73..6159191 100644 --- a/src/DrawingProgram/DrawingProgram.cpp +++ b/src/DrawingProgram/DrawingProgram.cpp @@ -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()); diff --git a/src/DrawingProgram/DrawingProgram.hpp b/src/DrawingProgram/DrawingProgram.hpp index 7d7cc76..bb3bd33 100644 --- a/src/DrawingProgram/DrawingProgram.hpp +++ b/src/DrawingProgram/DrawingProgram.hpp @@ -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); diff --git a/src/GUIStuff/ElementHelpers/ScrollAreaHelpers.cpp b/src/GUIStuff/ElementHelpers/ScrollAreaHelpers.cpp index cd18949..3b0c629 100644 --- a/src/GUIStuff/ElementHelpers/ScrollAreaHelpers.cpp +++ b/src/GUIStuff/ElementHelpers/ScrollAreaHelpers.cpp @@ -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) { diff --git a/src/GUIStuff/ElementHelpers/ScrollAreaHelpers.hpp b/src/GUIStuff/ElementHelpers/ScrollAreaHelpers.hpp index 3389931..2899f20 100644 --- a/src/GUIStuff/ElementHelpers/ScrollAreaHelpers.hpp +++ b/src/GUIStuff/ElementHelpers/ScrollAreaHelpers.hpp @@ -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 elementContent; std::function innerContentExtraCallback; }; diff --git a/src/GUIStuff/Elements/GridScrollArea.cpp b/src/GUIStuff/Elements/GridScrollArea.cpp index a0e04b8..202dbf4 100644 --- a/src/GUIStuff/Elements/GridScrollArea.cpp +++ b/src/GUIStuff/Elements/GridScrollArea.cpp @@ -24,6 +24,7 @@ void GridScrollArea::layout(const Clay_ElementId& id, const Options& o) { size_t entriesPerRow = std::max(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; diff --git a/src/GUIStuff/Elements/GridScrollArea.hpp b/src/GUIStuff/Elements/GridScrollArea.hpp index 1a45712..9da39ad 100644 --- a/src/GUIStuff/Elements/GridScrollArea.hpp +++ b/src/GUIStuff/Elements/GridScrollArea.hpp @@ -15,6 +15,7 @@ class GridScrollArea : public Element { float entryHeight; size_t entryCount; bool entryWidthIsMinimum = false; + ScrollArea::ScrollbarType scrollbar = ScrollArea::ScrollbarType::NORMAL; std::function elementContent; std::function innerContentExtraCallback; }; diff --git a/src/GUIStuff/Elements/ScrollArea.cpp b/src/GUIStuff/Elements/ScrollArea.cpp index d541f27..d4812e1 100644 --- a/src/GUIStuff/Elements/ScrollArea.cpp +++ b/src/GUIStuff/Elements/ScrollArea.cpp @@ -2,13 +2,13 @@ #include "../GUIManager.hpp" #include #include -#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("y scroll bar", [&] (LayoutElement*, const Clay_ElementId& lId) { + yScrollbar.scrollbar = gui.element("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("scroller", [&] (LayoutElement*, const Clay_ElementId& lId2) { + yScrollbar.scroller = gui.element("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("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("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(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) diff --git a/src/GUIStuff/Elements/ScrollArea.hpp b/src/GUIStuff/Elements/ScrollArea.hpp index d760065..30c8968 100644 --- a/src/GUIStuff/Elements/ScrollArea.hpp +++ b/src/GUIStuff/Elements/ScrollArea.hpp @@ -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}; diff --git a/src/Screens/PhoneDrawingProgramScreen.cpp b/src/Screens/PhoneDrawingProgramScreen.cpp index 5c474ee..5150a5a 100644 --- a/src/Screens/PhoneDrawingProgramScreen.cpp +++ b/src/Screens/PhoneDrawingProgramScreen.cpp @@ -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("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()); diff --git a/src/Screens/PhoneDrawingProgramScreen.hpp b/src/Screens/PhoneDrawingProgramScreen.hpp index 44dfda2..e172058 100644 --- a/src/Screens/PhoneDrawingProgramScreen.hpp +++ b/src/Screens/PhoneDrawingProgramScreen.hpp @@ -12,5 +12,6 @@ class PhoneDrawingProgramScreen : public DrawingProgramScreen { private: void save_files(); void top_toolbar(); + void bottom_toolbar(); void main_display(); }; diff --git a/src/Toolbar.cpp b/src/Toolbar.cpp index a92a214..044338a 100644 --- a/src/Toolbar.cpp +++ b/src/Toolbar.cpp @@ -291,7 +291,7 @@ void Toolbar::close_popup_gui() { gui.clipping_element("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("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("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("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("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); }