diff --git a/FlexLove.lua b/FlexLove.lua index e66254a..168e803 100644 --- a/FlexLove.lua +++ b/FlexLove.lua @@ -9,6 +9,7 @@ local utils = req("utils") local Units = req("Units") local Context = req("Context") local StateManager = req("StateManager") +local ErrorHandler = req("ErrorHandler") ---@type Element local Element = req("Element") @@ -26,6 +27,7 @@ local flexlove = Context -- Initialize Units module with Context dependency Units.initialize(Context) +Units.initializeErrorHandler(ErrorHandler) -- Add version and metadata flexlove._VERSION = "0.1.0" @@ -480,10 +482,10 @@ function flexlove.keypressed(key, scancode, isrepeat) end end -function flexlove.wheelmoved(x, y) +function flexlove.wheelmoved(dx, dy) local mx, my = love.mouse.getPosition() - local function findScrollableAtPosition(elements, mx, my) + local function findScrollableAtPosition(elements, x, y) for i = #elements, 1, -1 do local element = elements[i] @@ -492,9 +494,9 @@ function flexlove.wheelmoved(x, y) local bw = element._borderBoxWidth or (element.width + element.padding.left + element.padding.right) local bh = element._borderBoxHeight or (element.height + element.padding.top + element.padding.bottom) - if mx >= bx and mx <= bx + bw and my >= by and my <= by + bh then + if x >= bx and x <= bx + bw and y >= by and y <= by + bh then if #element.children > 0 then - local childResult = findScrollableAtPosition(element.children, mx, my) + local childResult = findScrollableAtPosition(element.children, x, y) if childResult then return childResult end @@ -521,12 +523,71 @@ function flexlove.wheelmoved(x, y) local bw = element._borderBoxWidth or (element.width + element.padding.left + element.padding.right) local bh = element._borderBoxHeight or (element.height + element.padding.top + element.padding.bottom) - if mx >= bx and mx <= bx + bw and my >= by and my <= by + bh then - local overflowX = element.overflowX or element.overflow - local overflowY = element.overflowY or element.overflow - if (overflowX == "scroll" or overflowX == "auto" or overflowY == "scroll" or overflowY == "auto") and (element._overflowX or element._overflowY) then - element:_handleWheelScroll(x, y) - return + -- Calculate scroll offset from parent chain + local scrollOffsetX = 0 + local scrollOffsetY = 0 + local current = element.parent + while current do + local overflowX = current.overflowX or current.overflow + local overflowY = current.overflowY or current.overflow + local hasScrollableOverflow = ( + overflowX == "scroll" + or overflowX == "auto" + or overflowY == "scroll" + or overflowY == "auto" + or overflowX == "hidden" + or overflowY == "hidden" + ) + if hasScrollableOverflow then + scrollOffsetX = scrollOffsetX + (current._scrollX or 0) + scrollOffsetY = scrollOffsetY + (current._scrollY or 0) + end + current = current.parent + end + + -- Adjust mouse position by scroll offset + local adjustedMx = mx + scrollOffsetX + local adjustedMy = my + scrollOffsetY + + -- Check if mouse is within element bounds + if adjustedMx >= bx and adjustedMx <= bx + bw and adjustedMy >= by and adjustedMy <= by + bh then + -- Check if mouse position is clipped by any parent + local isClipped = false + local parentCheck = element.parent + while parentCheck do + local parentOverflowX = parentCheck.overflowX or parentCheck.overflow + local parentOverflowY = parentCheck.overflowY or parentCheck.overflow + + if parentOverflowX == "hidden" or parentOverflowX == "scroll" or parentOverflowX == "auto" or + parentOverflowY == "hidden" or parentOverflowY == "scroll" or parentOverflowY == "auto" then + local parentX = parentCheck.x + parentCheck.padding.left + local parentY = parentCheck.y + parentCheck.padding.top + local parentW = parentCheck.width + local parentH = parentCheck.height + + if mx < parentX or mx > parentX + parentW or my < parentY or my > parentY + parentH then + isClipped = true + break + end + end + parentCheck = parentCheck.parent + end + + if not isClipped then + local overflowX = element.overflowX or element.overflow + local overflowY = element.overflowY or element.overflow + if (overflowX == "scroll" or overflowX == "auto" or overflowY == "scroll" or overflowY == "auto") and (element._overflowX or element._overflowY) then + element:_handleWheelScroll(dx, dy) + + -- Save scroll position to StateManager immediately in immediate mode + if element._stateId then + StateManager.updateState(element._stateId, { + _scrollX = element._scrollX, + _scrollY = element._scrollY, + }) + end + return + end end end end @@ -534,7 +595,7 @@ function flexlove.wheelmoved(x, y) -- In retained mode, use the old tree traversal method local scrollableElement = findScrollableAtPosition(flexlove.topElements, mx, my) if scrollableElement then - scrollableElement:_handleWheelScroll(x, y) + scrollableElement:_handleWheelScroll(dx, dy) end end end diff --git a/examples/01_flex_positioning.lua b/examples/01_flex_positioning.lua deleted file mode 100644 index e67b483..0000000 --- a/examples/01_flex_positioning.lua +++ /dev/null @@ -1,215 +0,0 @@ ---[[ - FlexLove Example 01: Flex Positioning - - This example demonstrates flexbox layouts in FlexLove: - - Flex direction (horizontal/vertical) - - Justify content (main axis alignment) - - Align items (cross axis alignment) - - Flex wrap behavior - - Run with: love /path/to/libs/examples/01_flex_positioning.lua -]] - --- Map Love to Lv to avoid duplicate definitions -local Lv = love - --- Load FlexLove from parent directory -local FlexLove = require("../FlexLove") -local Color = FlexLove.Color -local enums = FlexLove.enums - -function Lv.load() - -- Initialize FlexLove with base scaling - FlexLove.init({ - baseScale = { width = 1920, height = 1080 }, - }) - - -- Title - FlexLove.new({ - x = "2vw", - y = "2vh", - width = "96vw", - height = "6vh", - text = "FlexLove Example 01: Flex Positioning", - textSize = "4vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - }) - - -- ======================================== - -- Section 1: Horizontal Flex with Different JustifyContent Values - -- ======================================== - - local yOffset = 10 - - -- Label for justify-content section - FlexLove.new({ - x = "2vw", - y = yOffset .. "vh", - width = "96vw", - height = "3vh", - text = "Horizontal Flex - JustifyContent Options", - textSize = "2.5vh", - textColor = Color.new(0.9, 0.9, 0.9, 1), - }) - - yOffset = yOffset + 4 - - -- Demonstrate each justify-content option - local justifyOptions = { - { name = "flex-start", value = enums.JustifyContent.FLEX_START }, - { name = "center", value = enums.JustifyContent.CENTER }, - { name = "flex-end", value = enums.JustifyContent.FLEX_END }, - { name = "space-between", value = enums.JustifyContent.SPACE_BETWEEN }, - { name = "space-around", value = enums.JustifyContent.SPACE_AROUND }, - { name = "space-evenly", value = enums.JustifyContent.SPACE_EVENLY }, - } - - for _, option in ipairs(justifyOptions) do - -- Label for this justify option - FlexLove.new({ - x = "2vw", - y = yOffset .. "vh", - width = "15vw", - height = "3vh", - text = option.name, - textSize = "1.8vh", - textColor = Color.new(0.8, 0.8, 1, 1), - textAlign = enums.TextAlign.START, - }) - - -- Container demonstrating this justify-content value - local container = FlexLove.new({ - x = "18vw", - y = yOffset .. "vh", - width = "78vw", - height = "8vh", - positioning = enums.Positioning.FLEX, - flexDirection = enums.FlexDirection.HORIZONTAL, - justifyContent = option.value, - alignItems = enums.AlignItems.CENTER, - backgroundColor = Color.new(0.15, 0.15, 0.2, 1), - border = { top = true, right = true, bottom = true, left = true }, - borderColor = Color.new(0.3, 0.3, 0.4, 1), - }) - - -- Add child elements - local colors = { - Color.new(0.8, 0.3, 0.3, 1), - Color.new(0.3, 0.8, 0.3, 1), - Color.new(0.3, 0.3, 0.8, 1), - Color.new(0.8, 0.8, 0.3, 1), - } - - for j = 1, 4 do - FlexLove.new({ - parent = container, - width = "8vw", - height = "5vh", - backgroundColor = colors[j], - text = tostring(j), - textSize = "2vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - }) - end - - yOffset = yOffset + 9 - end - - -- ======================================== - -- Section 2: Vertical Flex with Different AlignItems Values - -- ======================================== - - yOffset = yOffset + 2 - - -- Label for align-items section - FlexLove.new({ - x = "2vw", - y = yOffset .. "vh", - width = "96vw", - height = "3vh", - text = "Vertical Flex - AlignItems Options", - textSize = "2.5vh", - textColor = Color.new(0.9, 0.9, 0.9, 1), - }) - - yOffset = yOffset + 4 - - -- Note: Due to space constraints, we'll show a subset in a horizontal layout - local alignOptions = { - { name = "stretch", value = enums.AlignItems.STRETCH }, - { name = "flex-start", value = enums.AlignItems.FLEX_START }, - { name = "center", value = enums.AlignItems.CENTER }, - { name = "flex-end", value = enums.AlignItems.FLEX_END }, - } - - local xOffset = 2 - local containerWidth = 22 - - for _, option in ipairs(alignOptions) do - -- Label for this align option - FlexLove.new({ - x = xOffset .. "vw", - y = yOffset .. "vh", - width = containerWidth .. "vw", - height = "2.5vh", - text = option.name, - textSize = "1.8vh", - textColor = Color.new(0.8, 1, 0.8, 1), - textAlign = enums.TextAlign.CENTER, - }) - - -- Container demonstrating this align-items value - local container = FlexLove.new({ - x = xOffset .. "vw", - y = (yOffset + 3) .. "vh", - width = containerWidth .. "vw", - height = "20vh", - positioning = enums.Positioning.FLEX, - flexDirection = enums.FlexDirection.VERTICAL, - justifyContent = enums.JustifyContent.FLEX_START, - alignItems = option.value, - gap = 5, - backgroundColor = Color.new(0.15, 0.2, 0.15, 1), - border = { top = true, right = true, bottom = true, left = true }, - borderColor = Color.new(0.3, 0.4, 0.3, 1), - }) - - -- Add child elements with varying widths - local widths = { "8vw", "12vw", "6vw" } - local colors = { - Color.new(0.9, 0.4, 0.4, 1), - Color.new(0.4, 0.9, 0.4, 1), - Color.new(0.4, 0.4, 0.9, 1), - } - - for j = 1, 3 do - FlexLove.new({ - parent = container, - width = option.value == enums.AlignItems.STRETCH and "auto" or widths[j], - height = "4vh", - backgroundColor = colors[j], - text = tostring(j), - textSize = "1.8vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - }) - end - - xOffset = xOffset + containerWidth + 2 - end -end - -function Lv.update(dt) - FlexLove.update(dt) -end - -function Lv.draw() - Lv.graphics.clear(0.05, 0.05, 0.08, 1) - FlexLove.draw() -end - -function Lv.resize(w, h) - FlexLove.resize(w, h) -end diff --git a/examples/02_grid_layout.lua b/examples/02_grid_layout.lua deleted file mode 100644 index 8872da7..0000000 --- a/examples/02_grid_layout.lua +++ /dev/null @@ -1,228 +0,0 @@ ---[[ - FlexLove Example 02: Grid Layout - - This example demonstrates grid layouts in FlexLove: - - Different grid configurations (2x2, 3x3, 4x2) - - Row and column gaps - - AlignItems behavior in grid cells - - Automatic grid cell positioning - - Run with: love /path/to/libs/examples/02_grid_layout.lua -]] - -local Lv = love - -local FlexLove = require("../FlexLove") -local Color = FlexLove.Color -local enums = FlexLove.enums - -function Lv.load() - FlexLove.init({ - baseScale = { width = 1920, height = 1080 } - }) - - -- Title - FlexLove.new({ - x = "2vw", - y = "2vh", - width = "96vw", - height = "6vh", - text = "FlexLove Example 02: Grid Layout", - textSize = "4vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - }) - - -- ======================================== - -- Section 1: 2x2 Grid with Gaps - -- ======================================== - - FlexLove.new({ - x = "2vw", - y = "10vh", - width = "30vw", - height = "3vh", - text = "2x2 Grid (rowGap: 10px, columnGap: 10px)", - textSize = "2vh", - textColor = Color.new(0.9, 0.9, 0.9, 1), - }) - - local grid2x2 = FlexLove.new({ - x = "2vw", - y = "14vh", - width = "30vw", - height = "30vh", - positioning = enums.Positioning.GRID, - gridRows = 2, - gridColumns = 2, - rowGap = 10, - columnGap = 10, - backgroundColor = Color.new(0.1, 0.1, 0.15, 1), - border = { top = true, right = true, bottom = true, left = true }, - borderColor = Color.new(0.3, 0.3, 0.4, 1), - }) - - -- Add 4 cells to 2x2 grid - local colors2x2 = { - Color.new(0.8, 0.3, 0.3, 1), - Color.new(0.3, 0.8, 0.3, 1), - Color.new(0.3, 0.3, 0.8, 1), - Color.new(0.8, 0.8, 0.3, 1), - } - - for j = 1, 4 do - FlexLove.new({ - parent = grid2x2, - backgroundColor = colors2x2[j], - text = "Cell " .. j, - textSize = "2.5vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - }) - end - - -- ======================================== - -- Section 2: 3x3 Grid with Different Gap Sizes - -- ======================================== - - FlexLove.new({ - x = "34vw", - y = "10vh", - width = "30vw", - height = "3vh", - text = "3x3 Grid (rowGap: 5px, columnGap: 15px)", - textSize = "2vh", - textColor = Color.new(0.9, 0.9, 0.9, 1), - }) - - local grid3x3 = FlexLove.new({ - x = "34vw", - y = "14vh", - width = "30vw", - height = "30vh", - positioning = enums.Positioning.GRID, - gridRows = 3, - gridColumns = 3, - rowGap = 5, - columnGap = 15, - backgroundColor = Color.new(0.1, 0.15, 0.1, 1), - border = { top = true, right = true, bottom = true, left = true }, - borderColor = Color.new(0.3, 0.4, 0.3, 1), - }) - - -- Add 9 cells to 3x3 grid - for j = 1, 9 do - local hue = (j - 1) / 9 - FlexLove.new({ - parent = grid3x3, - backgroundColor = Color.new(0.3 + hue * 0.5, 0.5, 0.7 - hue * 0.4, 1), - text = tostring(j), - textSize = "2vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - }) - end - - -- ======================================== - -- Section 3: 4x2 Grid with AlignItems - -- ======================================== - - FlexLove.new({ - x = "66vw", - y = "10vh", - width = "32vw", - height = "3vh", - text = "4x2 Grid (alignItems: center)", - textSize = "2vh", - textColor = Color.new(0.9, 0.9, 0.9, 1), - }) - - local grid4x2 = FlexLove.new({ - x = "66vw", - y = "14vh", - width = "32vw", - height = "30vh", - positioning = enums.Positioning.GRID, - gridRows = 4, - gridColumns = 2, - rowGap = 8, - columnGap = 8, - alignItems = enums.AlignItems.CENTER, - backgroundColor = Color.new(0.15, 0.1, 0.15, 1), - border = { top = true, right = true, bottom = true, left = true }, - borderColor = Color.new(0.4, 0.3, 0.4, 1), - }) - - -- Add 8 cells with varying content - for j = 1, 8 do - FlexLove.new({ - parent = grid4x2, - backgroundColor = Color.new(0.6, 0.4 + j * 0.05, 0.7 - j * 0.05, 1), - text = "Item " .. j, - textSize = "1.8vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - }) - end - - -- ======================================== - -- Section 4: Grid with Responsive Units (vw/vh gaps) - -- ======================================== - - FlexLove.new({ - x = "2vw", - y = "46vh", - width = "96vw", - height = "3vh", - text = "Grid with Responsive Gaps (rowGap: 2vh, columnGap: 2vw)", - textSize = "2vh", - textColor = Color.new(0.9, 0.9, 0.9, 1), - }) - - local gridResponsive = FlexLove.new({ - x = "2vw", - y = "50vh", - width = "96vw", - height = "45vh", - positioning = enums.Positioning.GRID, - gridRows = 2, - gridColumns = 5, - rowGap = "2vh", - columnGap = "2vw", - backgroundColor = Color.new(0.08, 0.08, 0.12, 1), - border = { top = true, right = true, bottom = true, left = true }, - borderColor = Color.new(0.25, 0.25, 0.35, 1), - }) - - -- Add 10 cells with gradient colors - for j = 1, 10 do - local progress = (j - 1) / 9 - FlexLove.new({ - parent = gridResponsive, - backgroundColor = Color.new( - 0.2 + progress * 0.6, - 0.4 + math.sin(progress * 3.14) * 0.4, - 0.8 - progress * 0.4, - 1 - ), - text = "Cell " .. j, - textSize = "2.5vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - cornerRadius = 5, - }) - end -end - -function Lv.update(dt) - FlexLove.update(dt) -end - -function Lv.draw() - Lv.graphics.clear(0.05, 0.05, 0.08, 1) - FlexLove.draw() -end - -function Lv.resize(w, h) - FlexLove.resize(w, h) -end diff --git a/examples/03_theming_system.lua b/examples/03_theming_system.lua deleted file mode 100644 index b577ffe..0000000 --- a/examples/03_theming_system.lua +++ /dev/null @@ -1,300 +0,0 @@ ---[[ - FlexLove Example 03: Theming System - - This example demonstrates the theming system in FlexLove: - - Loading and applying themes - - Theme components (button, panel, card) - - Theme states (normal, hover, pressed, disabled, active) - - Theme colors and fonts - - Run with: love /path/to/libs/examples/03_theming_system.lua -]] - -local Lv = love - -local FlexLove = require("../FlexLove") -local Color = FlexLove.Color -local enums = FlexLove.enums - -function Lv.load() - FlexLove.init({ - baseScale = { width = 1920, height = 1080 } - }) - - -- Load the space theme - FlexLove.loadTheme("space", "../themes/space") - - -- Title - FlexLove.new({ - x = "2vw", - y = "2vh", - width = "96vw", - height = "6vh", - text = "FlexLove Example 03: Theming System", - textSize = "4vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - }) - - -- ======================================== - -- Section 1: Theme Components - -- ======================================== - - FlexLove.new({ - x = "2vw", - y = "10vh", - width = "96vw", - height = "3vh", - text = "Theme Components - Space Theme", - textSize = "2.5vh", - textColor = Color.new(0.9, 0.9, 0.9, 1), - }) - - -- Card component - FlexLove.new({ - x = "2vw", - y = "14vh", - width = "30vw", - height = "20vh", - theme = "space", - themeComponent = "card", - text = "Card Component", - textSize = "2.5vh", - textColor = Color.new(0.8, 0.9, 1, 1), - textAlign = enums.TextAlign.CENTER, - }) - - -- Panel component - FlexLove.new({ - x = "34vw", - y = "14vh", - width = "30vw", - height = "20vh", - theme = "space", - themeComponent = "panel", - text = "Panel Component", - textSize = "2.5vh", - textColor = Color.new(0.8, 0.9, 1, 1), - textAlign = enums.TextAlign.CENTER, - }) - - -- Panel red component - FlexLove.new({ - x = "66vw", - y = "14vh", - width = "32vw", - height = "20vh", - theme = "space", - themeComponent = "panelred", - text = "Panel Red Component", - textSize = "2.5vh", - textColor = Color.new(1, 0.8, 0.8, 1), - textAlign = enums.TextAlign.CENTER, - }) - - -- ======================================== - -- Section 2: Button States - -- ======================================== - - FlexLove.new({ - x = "2vw", - y = "36vh", - width = "96vw", - height = "3vh", - text = "Button States - Hover and Click to See State Changes", - textSize = "2.5vh", - textColor = Color.new(0.9, 0.9, 0.9, 1), - }) - - -- Normal button (hover to see hover state, click to see pressed state) - FlexLove.new({ - x = "2vw", - y = "40vh", - width = "22vw", - height = "8vh", - theme = "space", - themeComponent = "button", - text = "Normal Button", - textSize = "2vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - onEvent = function(element, event) - if event.type == "click" then - print("Normal button clicked!") - end - end, - }) - - -- Active button (simulating active state) - local activeButton = FlexLove.new({ - x = "26vw", - y = "40vh", - width = "22vw", - height = "8vh", - theme = "space", - themeComponent = "button", - text = "Active Button", - textSize = "2vh", - textColor = Color.new(0.3, 1, 0.3, 1), - textAlign = enums.TextAlign.CENTER, - active = true, - onEvent = function(element, event) - if event.type == "click" then - element.active = not element.active - print("Active button toggled:", element.active) - end - end, - }) - - -- Disabled button - FlexLove.new({ - x = "50vw", - y = "40vh", - width = "22vw", - height = "8vh", - theme = "space", - themeComponent = "button", - text = "Disabled Button", - textSize = "2vh", - textColor = Color.new(0.5, 0.5, 0.5, 1), - textAlign = enums.TextAlign.CENTER, - disabled = true, - onEvent = function(element, event) - -- This won't be called because button is disabled - print("This shouldn't print!") - end, - }) - - -- Button with callback feedback - local clickCount = 0 - local counterButton = FlexLove.new({ - x = "74vw", - y = "40vh", - width = "24vw", - height = "8vh", - theme = "space", - themeComponent = "button", - text = "Click Me! (0)", - textSize = "2vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - onEvent = function(element, event) - if event.type == "click" then - clickCount = clickCount + 1 - element.text = "Click Me! (" .. clickCount .. ")" - end - end, - }) - - -- ======================================== - -- Section 3: Theme Colors and Fonts - -- ======================================== - - FlexLove.new({ - x = "2vw", - y = "50vh", - width = "96vw", - height = "3vh", - text = "Theme Colors and Fonts", - textSize = "2.5vh", - textColor = Color.new(0.9, 0.9, 0.9, 1), - }) - - -- Container showing theme colors - local colorContainer = FlexLove.new({ - x = "2vw", - y = "54vh", - width = "96vw", - height = "20vh", - positioning = enums.Positioning.FLEX, - flexDirection = enums.FlexDirection.HORIZONTAL, - justifyContent = enums.JustifyContent.SPACE_EVENLY, - alignItems = enums.AlignItems.CENTER, - backgroundColor = Color.new(0.1, 0.1, 0.15, 1), - border = { top = true, right = true, bottom = true, left = true }, - borderColor = Color.new(0.3, 0.3, 0.4, 1), - }) - - -- Primary color swatch - FlexLove.new({ - parent = colorContainer, - width = "20vw", - height = "15vh", - backgroundColor = Color.new(0.08, 0.75, 0.95, 1), -- Theme primary color - text = "Primary Color", - textSize = "2vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - cornerRadius = 5, - }) - - -- Secondary color swatch - FlexLove.new({ - parent = colorContainer, - width = "20vw", - height = "15vh", - backgroundColor = Color.new(0.15, 0.20, 0.25, 1), -- Theme secondary color - text = "Secondary Color", - textSize = "2vh", - textColor = Color.new(0.8, 0.9, 1, 1), - textAlign = enums.TextAlign.CENTER, - cornerRadius = 5, - }) - - -- Text color swatch - FlexLove.new({ - parent = colorContainer, - width = "20vw", - height = "15vh", - backgroundColor = Color.new(0.2, 0.2, 0.25, 1), - text = "Text Color", - textSize = "2vh", - textColor = Color.new(0.80, 0.90, 1.00, 1), -- Theme text color - textAlign = enums.TextAlign.CENTER, - cornerRadius = 5, - }) - - -- Text dark color swatch - FlexLove.new({ - parent = colorContainer, - width = "20vw", - height = "15vh", - backgroundColor = Color.new(0.25, 0.25, 0.3, 1), - text = "Text Dark Color", - textSize = "2vh", - textColor = Color.new(0.35, 0.40, 0.45, 1), -- Theme textDark color - textAlign = enums.TextAlign.CENTER, - cornerRadius = 5, - }) - - -- ======================================== - -- Section 4: Font Family from Theme - -- ======================================== - - FlexLove.new({ - x = "2vw", - y = "76vh", - width = "96vw", - height = "18vh", - theme = "space", - themeComponent = "card", - text = "This text uses the theme's default font (VT323)", - textSize = "3vh", - textColor = Color.new(0.8, 0.9, 1, 1), - textAlign = enums.TextAlign.CENTER, - fontFamily = "default", -- References theme font - }) -end - -function Lv.update(dt) - FlexLove.update(dt) -end - -function Lv.draw() - Lv.graphics.clear(0.05, 0.05, 0.08, 1) - FlexLove.draw() -end - -function Lv.resize(w, h) - FlexLove.resize(w, h) -end diff --git a/examples/04_responsive_units.lua b/examples/04_responsive_units.lua deleted file mode 100644 index 64586b9..0000000 --- a/examples/04_responsive_units.lua +++ /dev/null @@ -1,240 +0,0 @@ ---[[ - FlexLove Example 04: Responsive Units - - This example demonstrates responsive unit systems in FlexLove: - - Viewport units (vw, vh) - - Percentage units (%) - - Pixel units (px) - - How elements resize with the window - - Run with: love /path/to/libs/examples/04_responsive_units.lua - Try resizing the window to see responsive behavior! -]] - -local Lv = love - -local FlexLove = require("../FlexLove") -local Color = FlexLove.Color -local enums = FlexLove.enums - -function Lv.load() - FlexLove.init({ - baseScale = { width = 1920, height = 1080 } - }) - - -- Title - FlexLove.new({ - x = "2vw", - y = "2vh", - width = "96vw", - height = "6vh", - text = "FlexLove Example 04: Responsive Units - Try Resizing!", - textSize = "4vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - }) - - -- ======================================== - -- Section 1: Viewport Width Units (vw) - -- ======================================== - - FlexLove.new({ - x = "2vw", - y = "10vh", - width = "96vw", - height = "3vh", - text = "Viewport Width (vw) - Scales with window width", - textSize = "2.5vh", - textColor = Color.new(0.9, 0.9, 0.9, 1), - }) - - local vwContainer = FlexLove.new({ - x = "2vw", - y = "14vh", - width = "96vw", - height = "12vh", - positioning = enums.Positioning.FLEX, - flexDirection = enums.FlexDirection.HORIZONTAL, - justifyContent = enums.JustifyContent.SPACE_EVENLY, - alignItems = enums.AlignItems.CENTER, - backgroundColor = Color.new(0.1, 0.1, 0.15, 1), - border = { top = true, right = true, bottom = true, left = true }, - borderColor = Color.new(0.3, 0.3, 0.4, 1), - }) - - -- Elements with vw widths - local vwWidths = { "10vw", "15vw", "20vw", "25vw" } - local colors = { - Color.new(0.8, 0.3, 0.3, 1), - Color.new(0.3, 0.8, 0.3, 1), - Color.new(0.3, 0.3, 0.8, 1), - Color.new(0.8, 0.8, 0.3, 1), - } - - for i, width in ipairs(vwWidths) do - FlexLove.new({ - parent = vwContainer, - width = width, - height = "8vh", - backgroundColor = colors[i], - text = width, - textSize = "1.8vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - }) - end - - -- ======================================== - -- Section 2: Viewport Height Units (vh) - -- ======================================== - - FlexLove.new({ - x = "2vw", - y = "28vh", - width = "96vw", - height = "3vh", - text = "Viewport Height (vh) - Scales with window height", - textSize = "2.5vh", - textColor = Color.new(0.9, 0.9, 0.9, 1), - }) - - local vhContainer = FlexLove.new({ - x = "2vw", - y = "32vh", - width = "96vw", - height = "30vh", - positioning = enums.Positioning.FLEX, - flexDirection = enums.FlexDirection.HORIZONTAL, - justifyContent = enums.JustifyContent.SPACE_EVENLY, - alignItems = enums.AlignItems.FLEX_END, - backgroundColor = Color.new(0.1, 0.15, 0.1, 1), - border = { top = true, right = true, bottom = true, left = true }, - borderColor = Color.new(0.3, 0.4, 0.3, 1), - }) - - -- Elements with vh heights - local vhHeights = { "8vh", "12vh", "16vh", "20vh", "24vh" } - - for i, height in ipairs(vhHeights) do - local hue = (i - 1) / 4 - FlexLove.new({ - parent = vhContainer, - width = "16vw", - height = height, - backgroundColor = Color.new(0.3 + hue * 0.5, 0.5, 0.7 - hue * 0.4, 1), - text = height, - textSize = "1.8vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - }) - end - - -- ======================================== - -- Section 3: Percentage Units (%) - -- ======================================== - - FlexLove.new({ - x = "2vw", - y = "64vh", - width = "46vw", - height = "3vh", - text = "Percentage (%) - Relative to parent", - textSize = "2.5vh", - textColor = Color.new(0.9, 0.9, 0.9, 1), - }) - - local percentContainer = FlexLove.new({ - x = "2vw", - y = "68vh", - width = "46vw", - height = "28vh", - positioning = enums.Positioning.FLEX, - flexDirection = enums.FlexDirection.VERTICAL, - justifyContent = enums.JustifyContent.SPACE_EVENLY, - alignItems = enums.AlignItems.STRETCH, - backgroundColor = Color.new(0.15, 0.1, 0.15, 1), - border = { top = true, right = true, bottom = true, left = true }, - borderColor = Color.new(0.4, 0.3, 0.4, 1), - padding = { top = 10, right = 10, bottom = 10, left = 10 }, - }) - - -- Child elements with percentage widths - local percentWidths = { "25%", "50%", "75%", "100%" } - - for i, width in ipairs(percentWidths) do - local progress = (i - 1) / 3 - FlexLove.new({ - parent = percentContainer, - width = width, - height = "5vh", - backgroundColor = Color.new(0.6, 0.4 + progress * 0.4, 0.7 - progress * 0.4, 1), - text = width .. " of parent", - textSize = "1.8vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - }) - end - - -- ======================================== - -- Section 4: Pixel Units (px) - Fixed Size - -- ======================================== - - FlexLove.new({ - x = "50vw", - y = "64vh", - width = "48vw", - height = "3vh", - text = "Pixels (px) - Fixed size (doesn't resize)", - textSize = "2.5vh", - textColor = Color.new(0.9, 0.9, 0.9, 1), - }) - - local pxContainer = FlexLove.new({ - x = "50vw", - y = "68vh", - width = "48vw", - height = "28vh", - positioning = enums.Positioning.FLEX, - flexDirection = enums.FlexDirection.HORIZONTAL, - justifyContent = enums.JustifyContent.CENTER, - alignItems = enums.AlignItems.CENTER, - gap = 10, - backgroundColor = Color.new(0.1, 0.12, 0.15, 1), - border = { top = true, right = true, bottom = true, left = true }, - borderColor = Color.new(0.3, 0.35, 0.4, 1), - }) - - -- Fixed pixel size elements - local pxSizes = { - { w = 80, h = 80 }, - { w = 100, h = 100 }, - { w = 120, h = 120 }, - } - - for i, size in ipairs(pxSizes) do - FlexLove.new({ - parent = pxContainer, - width = size.w, - height = size.h, - backgroundColor = Color.new(0.8 - i * 0.2, 0.3 + i * 0.2, 0.5, 1), - text = size.w .. "px", - textSize = "1.8vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - cornerRadius = 5, - }) - end -end - -function Lv.update(dt) - FlexLove.update(dt) -end - -function Lv.draw() - Lv.graphics.clear(0.05, 0.05, 0.08, 1) - FlexLove.draw() -end - -function Lv.resize(w, h) - FlexLove.resize(w, h) -end diff --git a/examples/05_animations.lua b/examples/05_animations.lua deleted file mode 100644 index 30d5ef9..0000000 --- a/examples/05_animations.lua +++ /dev/null @@ -1,246 +0,0 @@ ---[[ - FlexLove Example 05: Animations - - This example demonstrates animation system in FlexLove: - - Fade animations - - Scale animations - - Custom animations with different easing functions - - Animation timing and interpolation - - Run with: love /path/to/libs/examples/05_animations.lua -]] - -local Lv = love - -local FlexLove = require("../FlexLove") -local Color = FlexLove.Color -local Animation = FlexLove.Animation -local enums = FlexLove.enums - --- Animation control variables -local fadeBox, scaleBox, easingBoxes - -function Lv.load() - FlexLove.init({ - baseScale = { width = 1920, height = 1080 } - }) - - -- Title - FlexLove.new({ - x = "2vw", - y = "2vh", - width = "96vw", - height = "6vh", - text = "FlexLove Example 05: Animations", - textSize = "4vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - }) - - -- ======================================== - -- Section 1: Fade Animation - -- ======================================== - - FlexLove.new({ - x = "2vw", - y = "10vh", - width = "46vw", - height = "3vh", - text = "Fade Animation - Click to trigger", - textSize = "2.5vh", - textColor = Color.new(0.9, 0.9, 0.9, 1), - }) - - fadeBox = FlexLove.new({ - x = "2vw", - y = "14vh", - width = "46vw", - height = "20vh", - backgroundColor = Color.new(0.3, 0.6, 0.9, 1), - text = "Click me to fade out and back in", - textSize = "2vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - cornerRadius = 10, - onEvent = function(element, event) - if event.type == "click" then - -- Fade out then fade in - local fadeOut = Animation.fade(1.0, 1.0, 0.0) - fadeOut.easing = function(t) return t * t end -- easeInQuad - element.animation = fadeOut - - -- Queue fade in after fade out completes - local startTime = Lv.timer.getTime() - element._fadeCallback = function(el, dt) - if Lv.timer.getTime() - startTime >= 1.0 then - local fadeIn = Animation.fade(1.0, 0.0, 1.0) - fadeIn.easing = function(t) return t * (2 - t) end -- easeOutQuad - el.animation = fadeIn - el._fadeCallback = nil - end - end - end - end, - }) - - -- ======================================== - -- Section 2: Scale Animation - -- ======================================== - - FlexLove.new({ - x = "50vw", - y = "10vh", - width = "48vw", - height = "3vh", - text = "Scale Animation - Click to trigger", - textSize = "2.5vh", - textColor = Color.new(0.9, 0.9, 0.9, 1), - }) - - scaleBox = FlexLove.new({ - x = "50vw", - y = "14vh", - width = 400, - height = 200, - backgroundColor = Color.new(0.9, 0.4, 0.4, 1), - text = "Click me to scale up", - textSize = "2vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - cornerRadius = 10, - onEvent = function(element, event) - if event.type == "click" then - -- Scale up - local scaleUp = Animation.scale( - 0.5, - { width = element.width, height = element.height }, - { width = element.width * 1.5, height = element.height * 1.5 } - ) - scaleUp.easing = function(t) return t < 0.5 and 2 * t * t or -1 + (4 - 2 * t) * t end -- easeInOutQuad - element.animation = scaleUp - - -- Queue scale down - local startTime = Lv.timer.getTime() - element._scaleCallback = function(el, dt) - if Lv.timer.getTime() - startTime >= 0.5 then - local scaleDown = Animation.scale( - 0.5, - { width = el.width, height = el.height }, - { width = 400, height = 200 } - ) - scaleDown.easing = function(t) return t < 0.5 and 2 * t * t or -1 + (4 - 2 * t) * t end - el.animation = scaleDown - el._scaleCallback = nil - end - end - end - end, - }) - - -- ======================================== - -- Section 3: Easing Functions Comparison - -- ======================================== - - FlexLove.new({ - x = "2vw", - y = "36vh", - width = "96vw", - height = "3vh", - text = "Easing Functions - Click any box to see different easing", - textSize = "2.5vh", - textColor = Color.new(0.9, 0.9, 0.9, 1), - }) - - local easingContainer = FlexLove.new({ - x = "2vw", - y = "40vh", - width = "96vw", - height = "56vh", - positioning = enums.Positioning.GRID, - gridRows = 3, - gridColumns = 3, - rowGap = "2vh", - columnGap = "2vw", - backgroundColor = Color.new(0.08, 0.08, 0.12, 1), - border = { top = true, right = true, bottom = true, left = true }, - borderColor = Color.new(0.25, 0.25, 0.35, 1), - padding = { top = 20, right = 20, bottom = 20, left = 20 }, - }) - - -- Different easing functions - local easings = { - { name = "Linear", func = function(t) return t end }, - { name = "EaseInQuad", func = function(t) return t * t end }, - { name = "EaseOutQuad", func = function(t) return t * (2 - t) end }, - { name = "EaseInOutQuad", func = function(t) return t < 0.5 and 2 * t * t or -1 + (4 - 2 * t) * t end }, - { name = "EaseInCubic", func = function(t) return t * t * t end }, - { name = "EaseOutCubic", func = function(t) local t1 = t - 1; return t1 * t1 * t1 + 1 end }, - { name = "EaseInQuart", func = function(t) return t * t * t * t end }, - { name = "EaseOutQuart", func = function(t) local t1 = t - 1; return 1 - t1 * t1 * t1 * t1 end }, - { name = "EaseInExpo", func = function(t) return t == 0 and 0 or math.pow(2, 10 * (t - 1)) end }, - } - - easingBoxes = {} - - for i, easing in ipairs(easings) do - local hue = (i - 1) / 8 - local box = FlexLove.new({ - parent = easingContainer, - backgroundColor = Color.new(0.2 + hue * 0.6, 0.4 + math.sin(hue * 3.14) * 0.4, 0.8 - hue * 0.4, 1), - text = easing.name, - textSize = "2vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - cornerRadius = 8, - onEvent = function(element, event) - if event.type == "click" then - -- Fade out and in with this easing - local fadeOut = Animation.fade(0.8, 1.0, 0.2) - fadeOut.easing = easing.func - element.animation = fadeOut - - local startTime = Lv.timer.getTime() - element._easingCallback = function(el, dt) - if Lv.timer.getTime() - startTime >= 0.8 then - local fadeIn = Animation.fade(0.8, 0.2, 1.0) - fadeIn.easing = easing.func - el.animation = fadeIn - el._easingCallback = nil - end - end - end - end, - }) - table.insert(easingBoxes, box) - end -end - -function Lv.update(dt) - -- Handle fade callback - if fadeBox and fadeBox._fadeCallback then - fadeBox._fadeCallback(fadeBox, dt) - end - - -- Handle scale callback - if scaleBox and scaleBox._scaleCallback then - scaleBox._scaleCallback(scaleBox, dt) - end - - -- Handle easing callbacks - for _, box in ipairs(easingBoxes) do - if box._easingCallback then - box._easingCallback(box, dt) - end - end - - FlexLove.update(dt) -end - -function Lv.draw() - Lv.graphics.clear(0.05, 0.05, 0.08, 1) - FlexLove.draw() -end - -function Lv.resize(w, h) - FlexLove.resize(w, h) -end diff --git a/examples/06_event_system.lua b/examples/06_event_system.lua deleted file mode 100644 index e3e4eab..0000000 --- a/examples/06_event_system.lua +++ /dev/null @@ -1,318 +0,0 @@ ---[[ - FlexLove Example 06: Event System - - This example demonstrates the event system in FlexLove: - - Click events (left, right, middle mouse buttons) - - Press and release events - - Event properties (position, modifiers, click count) - - Double-click detection - - Keyboard modifiers (Shift, Ctrl, Alt) - - Run with: love /path/to/libs/examples/06_event_system.lua -]] - -local Lv = love - -local FlexLove = require("../FlexLove") -local Color = FlexLove.Color -local enums = FlexLove.enums - --- Event log -local eventLog = {} -local maxLogEntries = 15 - -local function addLogEntry(text) - table.insert(eventLog, 1, text) - if #eventLog > maxLogEntries then - table.remove(eventLog) - end -end - -function Lv.load() - FlexLove.init({ - baseScale = { width = 1920, height = 1080 } - }) - - -- Title - FlexLove.new({ - x = "2vw", - y = "2vh", - width = "96vw", - height = "6vh", - text = "FlexLove Example 06: Event System", - textSize = "4vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - }) - - -- ======================================== - -- Section 1: Click Events - -- ======================================== - - FlexLove.new({ - x = "2vw", - y = "10vh", - width = "46vw", - height = "3vh", - text = "Click Events - Try left, right, middle mouse buttons", - textSize = "2vh", - textColor = Color.new(0.9, 0.9, 0.9, 1), - }) - - local clickBox = FlexLove.new({ - x = "2vw", - y = "14vh", - width = "46vw", - height = "20vh", - backgroundColor = Color.new(0.3, 0.5, 0.7, 1), - text = "Click me with different mouse buttons!", - textSize = "2vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - cornerRadius = 10, - onEvent = function(element, event) - local buttonName = event.button == 1 and "Left" or (event.button == 2 and "Right" or "Middle") - local eventTypeName = event.type:sub(1,1):upper() .. event.type:sub(2) - - if event.type == "click" or event.type == "rightclick" or event.type == "middleclick" then - addLogEntry(string.format("%s Click at (%.0f, %.0f) - Count: %d", - buttonName, event.x, event.y, event.clickCount)) - elseif event.type == "press" then - addLogEntry(string.format("%s Button Pressed at (%.0f, %.0f)", - buttonName, event.x, event.y)) - elseif event.type == "release" then - addLogEntry(string.format("%s Button Released at (%.0f, %.0f)", - buttonName, event.x, event.y)) - end - end, - }) - - -- ======================================== - -- Section 2: Keyboard Modifiers - -- ======================================== - - FlexLove.new({ - x = "50vw", - y = "10vh", - width = "48vw", - height = "3vh", - text = "Keyboard Modifiers - Hold Shift/Ctrl/Alt while clicking", - textSize = "2vh", - textColor = Color.new(0.9, 0.9, 0.9, 1), - }) - - local modifierBox = FlexLove.new({ - x = "50vw", - y = "14vh", - width = "48vw", - height = "20vh", - backgroundColor = Color.new(0.7, 0.4, 0.5, 1), - text = "Click with modifiers!", - textSize = "2vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - cornerRadius = 10, - onEvent = function(element, event) - if event.type == "click" then - local mods = {} - if event.modifiers.shift then table.insert(mods, "Shift") end - if event.modifiers.ctrl then table.insert(mods, "Ctrl") end - if event.modifiers.alt then table.insert(mods, "Alt") end - if event.modifiers.super then table.insert(mods, "Super") end - - local modText = #mods > 0 and table.concat(mods, "+") or "None" - addLogEntry(string.format("Click with modifiers: %s", modText)) - end - end, - }) - - -- ======================================== - -- Section 3: Double-Click Detection - -- ======================================== - - FlexLove.new({ - x = "2vw", - y = "36vh", - width = "46vw", - height = "3vh", - text = "Double-Click Detection", - textSize = "2vh", - textColor = Color.new(0.9, 0.9, 0.9, 1), - }) - - local doubleClickBox = FlexLove.new({ - x = "2vw", - y = "40vh", - width = "46vw", - height = "15vh", - backgroundColor = Color.new(0.5, 0.7, 0.4, 1), - text = "Double-click me!", - textSize = "2vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - cornerRadius = 10, - onEvent = function(element, event) - if event.type == "click" then - if event.clickCount == 1 then - addLogEntry("Single click detected") - elseif event.clickCount == 2 then - addLogEntry("DOUBLE CLICK detected!") - -- Visual feedback for double-click - element.backgroundColor = Color.new(0.9, 0.9, 0.3, 1) - elseif event.clickCount >= 3 then - addLogEntry(string.format("TRIPLE+ CLICK detected! (count: %d)", event.clickCount)) - element.backgroundColor = Color.new(0.9, 0.3, 0.9, 1) - end - - -- Reset color after a delay (simulated in update) - element._resetTime = Lv.timer.getTime() + 0.3 - end - end, - }) - - -- ======================================== - -- Section 4: Event Log Display - -- ======================================== - - FlexLove.new({ - x = "50vw", - y = "36vh", - width = "48vw", - height = "3vh", - text = "Event Log (most recent first)", - textSize = "2vh", - textColor = Color.new(0.9, 0.9, 0.9, 1), - }) - - -- Event log container - local logContainer = FlexLove.new({ - x = "50vw", - y = "40vh", - width = "48vw", - height = "56vh", - backgroundColor = Color.new(0.08, 0.08, 0.12, 1), - border = { top = true, right = true, bottom = true, left = true }, - borderColor = Color.new(0.25, 0.25, 0.35, 1), - cornerRadius = 5, - }) - - -- ======================================== - -- Section 5: Interactive Buttons - -- ======================================== - - FlexLove.new({ - x = "2vw", - y = "57vh", - width = "46vw", - height = "3vh", - text = "Interactive Buttons", - textSize = "2vh", - textColor = Color.new(0.9, 0.9, 0.9, 1), - }) - - local buttonContainer = FlexLove.new({ - x = "2vw", - y = "61vh", - width = "46vw", - height = "35vh", - positioning = enums.Positioning.FLEX, - flexDirection = enums.FlexDirection.VERTICAL, - justifyContent = enums.JustifyContent.SPACE_EVENLY, - alignItems = enums.AlignItems.STRETCH, - backgroundColor = Color.new(0.1, 0.1, 0.15, 1), - border = { top = true, right = true, bottom = true, left = true }, - borderColor = Color.new(0.3, 0.3, 0.4, 1), - padding = { top = 10, right = 10, bottom = 10, left = 10 }, - gap = 10, - }) - - -- Button 1: Press/Release events - FlexLove.new({ - parent = buttonContainer, - height = "8vh", - backgroundColor = Color.new(0.4, 0.5, 0.8, 1), - text = "Press and Release Events", - textSize = "1.8vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - cornerRadius = 5, - onEvent = function(element, event) - if event.type == "press" then - addLogEntry("Button 1: PRESSED") - element.backgroundColor = Color.new(0.2, 0.3, 0.6, 1) - elseif event.type == "release" then - addLogEntry("Button 1: RELEASED") - element.backgroundColor = Color.new(0.4, 0.5, 0.8, 1) - end - end, - }) - - -- Button 2: Click counter - local clickCounter = 0 - FlexLove.new({ - parent = buttonContainer, - height = "8vh", - backgroundColor = Color.new(0.8, 0.5, 0.4, 1), - text = "Click Counter: 0", - textSize = "1.8vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - cornerRadius = 5, - onEvent = function(element, event) - if event.type == "click" then - clickCounter = clickCounter + 1 - element.text = "Click Counter: " .. clickCounter - addLogEntry("Button 2: Click #" .. clickCounter) - end - end, - }) - - -- Button 3: Clear log - FlexLove.new({ - parent = buttonContainer, - height = "8vh", - backgroundColor = Color.new(0.6, 0.4, 0.6, 1), - text = "Clear Event Log", - textSize = "1.8vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - cornerRadius = 5, - onEvent = function(element, event) - if event.type == "click" then - eventLog = {} - addLogEntry("Log cleared!") - end - end, - }) -end - -function Lv.update(dt) - -- Reset double-click box color - if doubleClickBox and doubleClickBox._resetTime and Lv.timer.getTime() >= doubleClickBox._resetTime then - doubleClickBox.backgroundColor = Color.new(0.5, 0.7, 0.4, 1) - doubleClickBox._resetTime = nil - end - - FlexLove.update(dt) -end - -function Lv.draw() - Lv.graphics.clear(0.05, 0.05, 0.08, 1) - FlexLove.draw() - - -- Draw event log - Lv.graphics.setColor(0.8, 0.9, 1, 1) - local logX = Lv.graphics.getWidth() * 0.50 + 10 - local logY = Lv.graphics.getHeight() * 0.40 + 10 - local lineHeight = 20 - - for i, entry in ipairs(eventLog) do - local alpha = 1.0 - (i - 1) / maxLogEntries * 0.5 - Lv.graphics.setColor(0.8, 0.9, 1, alpha) - Lv.graphics.print(entry, logX, logY + (i - 1) * lineHeight) - end -end - -function Lv.resize(w, h) - FlexLove.resize(w, h) -end diff --git a/examples/07_text_rendering.lua b/examples/07_text_rendering.lua deleted file mode 100644 index d95ba76..0000000 --- a/examples/07_text_rendering.lua +++ /dev/null @@ -1,188 +0,0 @@ ---[[ - FlexLove Example 07: Text Rendering - - This example demonstrates text rendering features in FlexLove: - - Text alignment (start, center, end, justify) - - Text size presets (xxs, xs, sm, md, lg, xl, xxl, 3xl, 4xl) - - Font rendering with custom fonts - - Text wrapping and positioning - - Run with: love /path/to/libs/examples/07_text_rendering.lua -]] - -local Lv = love - -local FlexLove = require("../FlexLove") -local Color = FlexLove.Color -local enums = FlexLove.enums - -function Lv.load() - FlexLove.init({ - baseScale = { width = 1920, height = 1080 } - }) - - -- Title - FlexLove.new({ - x = "2vw", - y = "2vh", - width = "96vw", - height = "6vh", - text = "FlexLove Example 07: Text Rendering", - textSize = "4vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - }) - - -- ======================================== - -- Section 1: Text Alignment - -- ======================================== - - FlexLove.new({ - x = "2vw", - y = "10vh", - width = "96vw", - height = "3vh", - text = "Text Alignment Options", - textSize = "2.5vh", - textColor = Color.new(0.9, 0.9, 0.9, 1), - }) - - local alignments = { - { name = "START", value = enums.TextAlign.START }, - { name = "CENTER", value = enums.TextAlign.CENTER }, - { name = "END", value = enums.TextAlign.END }, - } - - local yOffset = 14 - - for _, align in ipairs(alignments) do - FlexLove.new({ - x = "2vw", - y = yOffset .. "vh", - width = "30vw", - height = "8vh", - backgroundColor = Color.new(0.15, 0.15, 0.2, 1), - text = "Align: " .. align.name, - textSize = "2vh", - textColor = Color.new(0.8, 0.9, 1, 1), - textAlign = align.value, - border = { top = true, right = true, bottom = true, left = true }, - borderColor = Color.new(0.3, 0.3, 0.4, 1), - cornerRadius = 5, - }) - yOffset = yOffset + 9 - end - - -- ======================================== - -- Section 2: Text Size Presets - -- ======================================== - - FlexLove.new({ - x = "34vw", - y = "10vh", - width = "64vw", - height = "3vh", - text = "Text Size Presets", - textSize = "2.5vh", - textColor = Color.new(0.9, 0.9, 0.9, 1), - }) - - local textSizes = { - { name = "XXS", value = "xxs" }, - { name = "XS", value = "xs" }, - { name = "SM", value = "sm" }, - { name = "MD", value = "md" }, - { name = "LG", value = "lg" }, - { name = "XL", value = "xl" }, - { name = "XXL", value = "xxl" }, - { name = "3XL", value = "3xl" }, - { name = "4XL", value = "4xl" }, - } - - local sizeContainer = FlexLove.new({ - x = "34vw", - y = "14vh", - width = "64vw", - height = "76vh", - positioning = enums.Positioning.FLEX, - flexDirection = enums.FlexDirection.VERTICAL, - justifyContent = enums.JustifyContent.FLEX_START, - alignItems = enums.AlignItems.STRETCH, - gap = 5, - backgroundColor = Color.new(0.08, 0.08, 0.12, 1), - border = { top = true, right = true, bottom = true, left = true }, - borderColor = Color.new(0.25, 0.25, 0.35, 1), - padding = { top = 10, right = 10, bottom = 10, left = 10 }, - }) - - for i, size in ipairs(textSizes) do - local hue = (i - 1) / 8 - FlexLove.new({ - parent = sizeContainer, - height = "7vh", - backgroundColor = Color.new(0.2 + hue * 0.3, 0.3 + hue * 0.2, 0.5 - hue * 0.2, 1), - text = size.name .. " - The quick brown fox jumps over the lazy dog", - textSize = size.value, - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.START, - cornerRadius = 3, - }) - end - - -- ======================================== - -- Section 3: Custom Font Sizes (vh units) - -- ======================================== - - FlexLove.new({ - x = "2vw", - y = "41vh", - width = "30vw", - height = "3vh", - text = "Custom Text Sizes (vh units)", - textSize = "2vh", - textColor = Color.new(0.9, 0.9, 0.9, 1), - }) - - local customSizes = { "1vh", "2vh", "3vh", "4vh", "5vh" } - - local customContainer = FlexLove.new({ - x = "2vw", - y = "45vh", - width = "30vw", - height = "45vh", - positioning = enums.Positioning.FLEX, - flexDirection = enums.FlexDirection.VERTICAL, - justifyContent = enums.JustifyContent.SPACE_EVENLY, - alignItems = enums.AlignItems.STRETCH, - backgroundColor = Color.new(0.1, 0.12, 0.15, 1), - border = { top = true, right = true, bottom = true, left = true }, - borderColor = Color.new(0.3, 0.35, 0.4, 1), - padding = { top = 10, right = 10, bottom = 10, left = 10 }, - }) - - for i, size in ipairs(customSizes) do - FlexLove.new({ - parent = customContainer, - backgroundColor = Color.new(0.3, 0.4 + i * 0.08, 0.6 - i * 0.08, 1), - text = size .. " text", - textSize = size, - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - cornerRadius = 3, - padding = { top = 5, right = 10, bottom = 5, left = 10 }, - }) - end -end - -function Lv.update(dt) - FlexLove.update(dt) -end - -function Lv.draw() - Lv.graphics.clear(0.05, 0.05, 0.08, 1) - FlexLove.draw() -end - -function Lv.resize(w, h) - FlexLove.resize(w, h) -end diff --git a/examples/08_absolute_relative_positioning.lua b/examples/08_absolute_relative_positioning.lua deleted file mode 100644 index 2104af2..0000000 --- a/examples/08_absolute_relative_positioning.lua +++ /dev/null @@ -1,235 +0,0 @@ ---[[ - FlexLove Example 08: Absolute vs Relative Positioning - - This example demonstrates positioning modes in FlexLove: - - Absolute positioning (fixed coordinates) - - Relative positioning (relative to siblings) - - Comparison between the two modes - - Practical use cases - - Run with: love /path/to/libs/examples/08_absolute_relative_positioning.lua -]] - -local Lv = love - -local FlexLove = require("../FlexLove") -local Color = FlexLove.Color -local enums = FlexLove.enums - -function Lv.load() - FlexLove.init({ - baseScale = { width = 1920, height = 1080 } - }) - - -- Title - FlexLove.new({ - x = "2vw", - y = "2vh", - width = "96vw", - height = "6vh", - text = "FlexLove Example 08: Absolute vs Relative Positioning", - textSize = "4vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - }) - - -- ======================================== - -- Section 1: Absolute Positioning - -- ======================================== - - FlexLove.new({ - x = "2vw", - y = "10vh", - width = "46vw", - height = "3vh", - text = "Absolute Positioning - Fixed coordinates", - textSize = "2.5vh", - textColor = Color.new(0.9, 0.9, 0.9, 1), - }) - - local absoluteContainer = FlexLove.new({ - x = "2vw", - y = "14vh", - width = "46vw", - height = "40vh", - positioning = enums.Positioning.ABSOLUTE, - backgroundColor = Color.new(0.1, 0.1, 0.15, 1), - border = { top = true, right = true, bottom = true, left = true }, - borderColor = Color.new(0.3, 0.3, 0.4, 1), - }) - - -- Absolute positioned children - FlexLove.new({ - parent = absoluteContainer, - x = 20, - y = 20, - width = 150, - height = 80, - positioning = enums.Positioning.ABSOLUTE, - backgroundColor = Color.new(0.8, 0.3, 0.3, 1), - text = "x:20, y:20", - textSize = "1.8vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - cornerRadius = 5, - }) - - FlexLove.new({ - parent = absoluteContainer, - x = 200, - y = 50, - width = 150, - height = 80, - positioning = enums.Positioning.ABSOLUTE, - backgroundColor = Color.new(0.3, 0.8, 0.3, 1), - text = "x:200, y:50", - textSize = "1.8vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - cornerRadius = 5, - }) - - FlexLove.new({ - parent = absoluteContainer, - x = 100, - y = 150, - width = 150, - height = 80, - positioning = enums.Positioning.ABSOLUTE, - backgroundColor = Color.new(0.3, 0.3, 0.8, 1), - text = "x:100, y:150", - textSize = "1.8vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - cornerRadius = 5, - }) - - FlexLove.new({ - parent = absoluteContainer, - x = 280, - y = 180, - width = 150, - height = 80, - positioning = enums.Positioning.ABSOLUTE, - backgroundColor = Color.new(0.8, 0.8, 0.3, 1), - text = "x:280, y:180", - textSize = "1.8vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - cornerRadius = 5, - }) - - -- ======================================== - -- Section 2: Relative Positioning - -- ======================================== - - FlexLove.new({ - x = "50vw", - y = "10vh", - width = "48vw", - height = "3vh", - text = "Relative Positioning - Flows with siblings", - textSize = "2.5vh", - textColor = Color.new(0.9, 0.9, 0.9, 1), - }) - - local relativeContainer = FlexLove.new({ - x = "50vw", - y = "14vh", - width = "48vw", - height = "40vh", - positioning = enums.Positioning.RELATIVE, - backgroundColor = Color.new(0.1, 0.15, 0.1, 1), - border = { top = true, right = true, bottom = true, left = true }, - borderColor = Color.new(0.3, 0.4, 0.3, 1), - padding = { top = 10, right = 10, bottom = 10, left = 10 }, - }) - - -- Relative positioned children (flow naturally) - local relativeColors = { - Color.new(0.8, 0.3, 0.3, 1), - Color.new(0.3, 0.8, 0.3, 1), - Color.new(0.3, 0.3, 0.8, 1), - Color.new(0.8, 0.8, 0.3, 1), - } - - for i = 1, 4 do - FlexLove.new({ - parent = relativeContainer, - width = "45%", - height = "8vh", - positioning = enums.Positioning.RELATIVE, - backgroundColor = relativeColors[i], - text = "Element " .. i .. " (relative)", - textSize = "1.8vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - cornerRadius = 5, - margin = { top = 5, right = 5, bottom = 5, left = 5 }, - }) - end - - -- ======================================== - -- Section 3: Comparison with Overlapping - -- ======================================== - - FlexLove.new({ - x = "2vw", - y = "56vh", - width = "96vw", - height = "3vh", - text = "Absolute Positioning Allows Overlapping", - textSize = "2.5vh", - textColor = Color.new(0.9, 0.9, 0.9, 1), - }) - - local overlapContainer = FlexLove.new({ - x = "2vw", - y = "60vh", - width = "96vw", - height = "36vh", - positioning = enums.Positioning.ABSOLUTE, - backgroundColor = Color.new(0.08, 0.08, 0.12, 1), - border = { top = true, right = true, bottom = true, left = true }, - borderColor = Color.new(0.25, 0.25, 0.35, 1), - }) - - -- Create overlapping elements - local overlapColors = { - Color.new(0.9, 0.3, 0.3, 0.7), - Color.new(0.3, 0.9, 0.3, 0.7), - Color.new(0.3, 0.3, 0.9, 0.7), - Color.new(0.9, 0.9, 0.3, 0.7), - } - - for i = 1, 4 do - FlexLove.new({ - parent = overlapContainer, - x = 50 + (i - 1) * 60, - y = 30 + (i - 1) * 40, - width = 300, - height = 150, - positioning = enums.Positioning.ABSOLUTE, - backgroundColor = overlapColors[i], - text = "Layer " .. i, - textSize = "2.5vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - cornerRadius = 10, - z = i, -- Z-index for layering - }) - end -end - -function Lv.update(dt) - FlexLove.update(dt) -end - -function Lv.draw() - Lv.graphics.clear(0.05, 0.05, 0.08, 1) - FlexLove.draw() -end - -function Lv.resize(w, h) - FlexLove.resize(w, h) -end diff --git a/examples/09_styling_visual_effects.lua b/examples/09_styling_visual_effects.lua deleted file mode 100644 index 70a5f0d..0000000 --- a/examples/09_styling_visual_effects.lua +++ /dev/null @@ -1,280 +0,0 @@ ---[[ - FlexLove Example 09: Styling and Visual Effects - - This example demonstrates styling and visual effects: - - Corner radius (uniform and individual corners) - - Borders (different sides) - - Opacity levels - - Background colors - - Blur effects (contentBlur and backdropBlur) - - Run with: love /path/to/libs/examples/09_styling_visual_effects.lua -]] - -local Lv = love - -local FlexLove = require("../FlexLove") -local Color = FlexLove.Color -local enums = FlexLove.enums - -function Lv.load() - FlexLove.init({ - baseScale = { width = 1920, height = 1080 } - }) - - -- Title - FlexLove.new({ - x = "2vw", - y = "2vh", - width = "96vw", - height = "5vh", - text = "FlexLove Example 09: Styling and Visual Effects", - textSize = "3.5vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - }) - - -- ======================================== - -- Section 1: Corner Radius - -- ======================================== - - FlexLove.new({ - x = "2vw", - y = "9vh", - width = "46vw", - height = "3vh", - text = "Corner Radius", - textSize = "2.5vh", - textColor = Color.new(0.9, 0.9, 0.9, 1), - }) - - -- Uniform corner radius - FlexLove.new({ - x = "2vw", - y = "13vh", - width = "14vw", - height = "12vh", - backgroundColor = Color.new(0.6, 0.3, 0.7, 1), - cornerRadius = 5, - text = "radius: 5", - textSize = "1.8vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - }) - - FlexLove.new({ - x = "17vw", - y = "13vh", - width = "14vw", - height = "12vh", - backgroundColor = Color.new(0.3, 0.6, 0.7, 1), - cornerRadius = 15, - text = "radius: 15", - textSize = "1.8vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - }) - - -- Individual corner radius - FlexLove.new({ - x = "32vw", - y = "13vh", - width = "16vw", - height = "12vh", - backgroundColor = Color.new(0.7, 0.6, 0.3, 1), - cornerRadius = { - topLeft = 0, - topRight = 20, - bottomLeft = 20, - bottomRight = 0, - }, - text = "Individual\ncorners", - textSize = "1.8vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - }) - - -- ======================================== - -- Section 2: Borders - -- ======================================== - - FlexLove.new({ - x = "50vw", - y = "9vh", - width = "48vw", - height = "3vh", - text = "Borders", - textSize = "2.5vh", - textColor = Color.new(0.9, 0.9, 0.9, 1), - }) - - -- All borders - FlexLove.new({ - x = "50vw", - y = "13vh", - width = "14vw", - height = "12vh", - backgroundColor = Color.new(0.2, 0.2, 0.3, 1), - border = { top = true, right = true, bottom = true, left = true }, - borderColor = Color.new(0.8, 0.4, 0.4, 1), - text = "All sides", - textSize = "1.8vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - }) - - -- Top and bottom borders - FlexLove.new({ - x = "65vw", - y = "13vh", - width = "14vw", - height = "12vh", - backgroundColor = Color.new(0.2, 0.3, 0.2, 1), - border = { top = true, bottom = true }, - borderColor = Color.new(0.4, 0.8, 0.4, 1), - text = "Top & Bottom", - textSize = "1.8vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - }) - - -- Left border only - FlexLove.new({ - x = "80vw", - y = "13vh", - width = "16vw", - height = "12vh", - backgroundColor = Color.new(0.2, 0.2, 0.3, 1), - border = { left = true }, - borderColor = Color.new(0.4, 0.4, 0.8, 1), - text = "Left only", - textSize = "1.8vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - }) - - -- ======================================== - -- Section 3: Opacity - -- ======================================== - - FlexLove.new({ - x = "2vw", - y = "27vh", - width = "96vw", - height = "3vh", - text = "Opacity Levels", - textSize = "2.5vh", - textColor = Color.new(0.9, 0.9, 0.9, 1), - }) - - local opacityLevels = { 1.0, 0.75, 0.5, 0.25 } - - for i, opacity in ipairs(opacityLevels) do - FlexLove.new({ - x = (2 + (i - 1) * 24) .. "vw", - y = "31vh", - width = "22vw", - height = "12vh", - backgroundColor = Color.new(0.8, 0.3, 0.5, 1), - opacity = opacity, - text = "Opacity: " .. opacity, - textSize = "2vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - cornerRadius = 8, - }) - end - - -- ======================================== - -- Section 4: Background Colors - -- ======================================== - - FlexLove.new({ - x = "2vw", - y = "45vh", - width = "96vw", - height = "3vh", - text = "Background Colors", - textSize = "2.5vh", - textColor = Color.new(0.9, 0.9, 0.9, 1), - }) - - -- Gradient-like colors - for i = 1, 8 do - local hue = (i - 1) / 7 - FlexLove.new({ - x = (2 + (i - 1) * 12) .. "vw", - y = "49vh", - width = "11vw", - height = "18vh", - backgroundColor = Color.new( - 0.3 + hue * 0.5, - 0.5 + math.sin(hue * 3.14) * 0.3, - 0.8 - hue * 0.5, - 1 - ), - text = tostring(i), - textSize = "3vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - cornerRadius = 5, - }) - end - - -- ======================================== - -- Section 5: Blur Effects (if supported) - -- ======================================== - - FlexLove.new({ - x = "2vw", - y = "69vh", - width = "96vw", - height = "3vh", - text = "Blur Effects (contentBlur & backdropBlur)", - textSize = "2.5vh", - textColor = Color.new(0.9, 0.9, 0.9, 1), - }) - - -- Content blur example - FlexLove.new({ - x = "2vw", - y = "73vh", - width = "46vw", - height = "22vh", - backgroundColor = Color.new(0.3, 0.4, 0.6, 0.8), - contentBlur = { intensity = 5, quality = 3 }, - text = "Content Blur\n(blurs this element)", - textSize = "2vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - cornerRadius = 10, - }) - - -- Backdrop blur example - FlexLove.new({ - x = "50vw", - y = "73vh", - width = "46vw", - height = "22vh", - backgroundColor = Color.new(0.6, 0.4, 0.3, 0.6), - backdropBlur = { intensity = 10, quality = 5 }, - text = "Backdrop Blur\n(blurs background)", - textSize = "2vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - cornerRadius = 10, - }) -end - -function Lv.update(dt) - FlexLove.update(dt) -end - -function Lv.draw() - Lv.graphics.clear(0.05, 0.05, 0.08, 1) - FlexLove.draw() -end - -function Lv.resize(w, h) - FlexLove.resize(w, h) -end diff --git a/examples/10_padding_margins.lua b/examples/10_padding_margins.lua deleted file mode 100644 index ddbde77..0000000 --- a/examples/10_padding_margins.lua +++ /dev/null @@ -1,205 +0,0 @@ ---[[ - FlexLove Example 10: Padding and Margins - - This example demonstrates padding and margin spacing: - - Uniform padding - - Individual padding sides - - Uniform margins - - Individual margin sides - - Visual indicators for spacing - - Run with: love /path/to/libs/examples/10_padding_margins.lua -]] - -local Lv = love - -local FlexLove = require("../FlexLove") -local Color = FlexLove.Color -local enums = FlexLove.enums - -function Lv.load() - FlexLove.init({ - baseScale = { width = 1920, height = 1080 } - }) - - -- Title - FlexLove.new({ - x = "2vw", - y = "2vh", - width = "96vw", - height = "5vh", - text = "FlexLove Example 10: Padding and Margins", - textSize = "3.5vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - }) - - -- Section 1: Padding Examples - FlexLove.new({ - x = "2vw", - y = "9vh", - width = "46vw", - height = "3vh", - text = "Padding (internal spacing)", - textSize = "2.5vh", - textColor = Color.new(0.9, 0.9, 0.9, 1), - }) - - -- Uniform padding - local container1 = FlexLove.new({ - x = "2vw", - y = "13vh", - width = "22vw", - height = "18vh", - backgroundColor = Color.new(0.3, 0.4, 0.6, 1), - padding = { top = 20, right = 20, bottom = 20, left = 20 }, - }) - - FlexLove.new({ - parent = container1, - width = "auto", - height = "auto", - backgroundColor = Color.new(0.8, 0.6, 0.3, 1), - text = "Uniform\npadding: 20px", - textSize = "2vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - }) - - -- Individual padding sides - local container2 = FlexLove.new({ - x = "26vw", - y = "13vh", - width = "22vw", - height = "18vh", - backgroundColor = Color.new(0.4, 0.6, 0.3, 1), - padding = { top = 30, right = 10, bottom = 30, left = 10 }, - }) - - FlexLove.new({ - parent = container2, - width = "auto", - height = "auto", - backgroundColor = Color.new(0.8, 0.3, 0.6, 1), - text = "Individual\ntop/bottom: 30px\nleft/right: 10px", - textSize = "1.8vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - }) - - -- Section 2: Margin Examples - FlexLove.new({ - x = "50vw", - y = "9vh", - width = "48vw", - height = "3vh", - text = "Margins (external spacing)", - textSize = "2.5vh", - textColor = Color.new(0.9, 0.9, 0.9, 1), - }) - - -- Container to show margins - local marginContainer = FlexLove.new({ - x = "50vw", - y = "13vh", - width = "46vw", - height = "38vh", - positioning = enums.Positioning.FLEX, - flexDirection = enums.FlexDirection.VERTICAL, - backgroundColor = Color.new(0.15, 0.15, 0.2, 1), - }) - - -- Elements with different margins - FlexLove.new({ - parent = marginContainer, - width = "40vw", - height = "6vh", - backgroundColor = Color.new(0.7, 0.3, 0.3, 1), - margin = { top = 10, right = 10, bottom = 10, left = 10 }, - text = "Uniform margin: 10px", - textSize = "2vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - }) - - FlexLove.new({ - parent = marginContainer, - width = "40vw", - height = "6vh", - backgroundColor = Color.new(0.3, 0.7, 0.3, 1), - margin = { top = 5, right = 30, bottom = 5, left = 30 }, - text = "Horizontal margin: 30px", - textSize = "2vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - }) - - FlexLove.new({ - parent = marginContainer, - width = "40vw", - height = "6vh", - backgroundColor = Color.new(0.3, 0.3, 0.7, 1), - margin = { top = 20, right = 10, bottom = 20, left = 10 }, - text = "Vertical margin: 20px", - textSize = "2vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - }) - - -- Section 3: Combined Padding and Margins - FlexLove.new({ - x = "2vw", - y = "33vh", - width = "46vw", - height = "3vh", - text = "Combined Padding & Margins", - textSize = "2.5vh", - textColor = Color.new(0.9, 0.9, 0.9, 1), - }) - - local combinedContainer = FlexLove.new({ - x = "2vw", - y = "37vh", - width = "46vw", - height = "58vh", - positioning = enums.Positioning.FLEX, - flexDirection = enums.FlexDirection.VERTICAL, - backgroundColor = Color.new(0.1, 0.1, 0.15, 1), - padding = { top = 15, right = 15, bottom = 15, left = 15 }, - }) - - for i = 1, 3 do - local box = FlexLove.new({ - parent = combinedContainer, - width = "auto", - height = "14vh", - backgroundColor = Color.new(0.5 + i * 0.1, 0.4, 0.6 - i * 0.1, 1), - margin = { top = 10, right = 0, bottom = 10, left = 0 }, - padding = { top = 15, right = 15, bottom = 15, left = 15 }, - }) - - FlexLove.new({ - parent = box, - width = "auto", - height = "auto", - backgroundColor = Color.new(0.2, 0.2, 0.3, 1), - text = "Box " .. i .. "\nPadding: 15px\nMargin: 10px", - textSize = "1.8vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - }) - end -end - -function Lv.update(dt) - FlexLove.update(dt) -end - -function Lv.draw() - Lv.graphics.clear(0.05, 0.05, 0.08, 1) - FlexLove.draw() -end - -function Lv.resize(w, h) - FlexLove.resize(w, h) -end diff --git a/examples/11_input_controls.lua b/examples/11_input_controls.lua deleted file mode 100644 index e6d2ec0..0000000 --- a/examples/11_input_controls.lua +++ /dev/null @@ -1,148 +0,0 @@ ---[[ - FlexLove Example 11: Input Controls - - This example demonstrates input controls (if available): - - Text input fields - - Keyboard input handling - - Focus management - - Run with: love /path/to/libs/examples/11_input_controls.lua -]] - -local Lv = love - -local FlexLove = require("../FlexLove") -local Color = FlexLove.Color -local enums = FlexLove.enums - -function Lv.load() - FlexLove.init({ - baseScale = { width = 1920, height = 1080 } - }) - - -- Title - FlexLove.new({ - x = "2vw", - y = "2vh", - width = "96vw", - height = "6vh", - text = "FlexLove Example 11: Input Controls", - textSize = "4vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - }) - - -- Note: Input controls may require additional setup in FlexLove - FlexLove.new({ - x = "2vw", - y = "10vh", - width = "96vw", - height = "4vh", - text = "Note: This example demonstrates basic input handling patterns", - textSize = "2vh", - textColor = Color.new(0.8, 0.8, 0.8, 1), - textAlign = enums.TextAlign.CENTER, - }) - - -- Interactive buttons - local counter = 0 - local counterDisplay = FlexLove.new({ - x = "35vw", - y = "20vh", - width = "30vw", - height = "10vh", - backgroundColor = Color.new(0.2, 0.2, 0.3, 1), - text = "Counter: 0", - textSize = "4vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - cornerRadius = 10, - }) - - -- Increment button - FlexLove.new({ - x = "20vw", - y = "35vh", - width = "20vw", - height = "8vh", - backgroundColor = Color.new(0.3, 0.6, 0.3, 1), - text = "Increment (+)", - textSize = "2.5vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - cornerRadius = 8, - onEvent = function() - counter = counter + 1 - counterDisplay.text = "Counter: " .. counter - end - }) - - -- Decrement button - FlexLove.new({ - x = "60vw", - y = "35vh", - width = "20vw", - height = "8vh", - backgroundColor = Color.new(0.6, 0.3, 0.3, 1), - text = "Decrement (-)", - textSize = "2.5vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - cornerRadius = 8, - onEvent = function() - counter = counter - 1 - counterDisplay.text = "Counter: " .. counter - end - }) - - -- Reset button - FlexLove.new({ - x = "40vw", - y = "46vh", - width = "20vw", - height = "8vh", - backgroundColor = Color.new(0.4, 0.4, 0.6, 1), - text = "Reset", - textSize = "2.5vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - cornerRadius = 8, - onEvent = function() - counter = 0 - counterDisplay.text = "Counter: " .. counter - end - }) - - -- Keyboard input info - FlexLove.new({ - x = "2vw", - y = "60vh", - width = "96vw", - height = "30vh", - backgroundColor = Color.new(0.15, 0.15, 0.2, 1), - text = "Keyboard Input:\n\nFlexLove supports keyboard input through Element properties:\n\n" .. - "- Use 'inputType' property for text input fields\n" .. - "- Handle onTextInput, onTextChange, onEnter callbacks\n" .. - "- Manage focus with onFocus and onBlur events\n\n" .. - "See FlexLove documentation for full input API", - textSize = "2vh", - textColor = Color.new(0.9, 0.9, 0.9, 1), - textAlign = enums.TextAlign.CENTER, - cornerRadius = 10, - border = { top = true, right = true, bottom = true, left = true }, - borderColor = Color.new(0.4, 0.4, 0.5, 1), - }) -end - -function Lv.update(dt) - FlexLove.update(dt) -end - -function Lv.draw() - Lv.graphics.clear(0.05, 0.05, 0.08, 1) - FlexLove.draw() -end - -function Lv.resize(w, h) - FlexLove.resize(w, h) -end diff --git a/examples/12_z_index_layering.lua b/examples/12_z_index_layering.lua deleted file mode 100644 index b283114..0000000 --- a/examples/12_z_index_layering.lua +++ /dev/null @@ -1,203 +0,0 @@ ---[[ - FlexLove Example 12: Z-Index Layering - - This example demonstrates z-index for element layering: - - Different z-index values - - Overlapping elements - - Layer ordering - - Run with: love /path/to/libs/examples/12_z_index_layering.lua -]] - -local Lv = love - -local FlexLove = require("../FlexLove") -local Color = FlexLove.Color -local enums = FlexLove.enums - -function Lv.load() - FlexLove.init({ - baseScale = { width = 1920, height = 1080 } - }) - - -- Title - FlexLove.new({ - x = "2vw", - y = "2vh", - width = "96vw", - height = "6vh", - text = "FlexLove Example 12: Z-Index Layering", - textSize = "4vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - }) - - -- Description - FlexLove.new({ - x = "2vw", - y = "10vh", - width = "96vw", - height = "3vh", - text = "Elements with higher z-index values appear on top", - textSize = "2vh", - textColor = Color.new(0.8, 0.8, 0.8, 1), - textAlign = enums.TextAlign.CENTER, - }) - - -- Section 1: Overlapping boxes with different z-index - FlexLove.new({ - x = "2vw", - y = "15vh", - width = "46vw", - height = "3vh", - text = "Overlapping Elements", - textSize = "2.5vh", - textColor = Color.new(0.9, 0.9, 0.9, 1), - }) - - -- Box 1 (z-index: 1) - FlexLove.new({ - x = "5vw", - y = "20vh", - width = "20vw", - height = "20vh", - z = 1, - backgroundColor = Color.new(0.8, 0.3, 0.3, 1), - text = "Z-Index: 1", - textSize = "2.5vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - cornerRadius = 10, - }) - - -- Box 2 (z-index: 2) - overlaps Box 1 - FlexLove.new({ - x = "12vw", - y = "25vh", - width = "20vw", - height = "20vh", - z = 2, - backgroundColor = Color.new(0.3, 0.8, 0.3, 1), - text = "Z-Index: 2", - textSize = "2.5vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - cornerRadius = 10, - }) - - -- Box 3 (z-index: 3) - overlaps Box 1 and 2 - FlexLove.new({ - x = "19vw", - y = "30vh", - width = "20vw", - height = "20vh", - z = 3, - backgroundColor = Color.new(0.3, 0.3, 0.8, 1), - text = "Z-Index: 3", - textSize = "2.5vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - cornerRadius = 10, - }) - - -- Section 2: Cards with different layers - FlexLove.new({ - x = "50vw", - y = "15vh", - width = "48vw", - height = "3vh", - text = "Layered Cards", - textSize = "2.5vh", - textColor = Color.new(0.9, 0.9, 0.9, 1), - }) - - -- Create a stack of cards - for i = 1, 5 do - FlexLove.new({ - x = (52 + i * 2) .. "vw", - y = (18 + i * 3) .. "vh", - width = "22vw", - height = "15vh", - z = i, - backgroundColor = Color.new(0.3 + i * 0.1, 0.4, 0.7 - i * 0.1, 1), - text = "Card " .. i .. "\nZ-Index: " .. i, - textSize = "2vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - cornerRadius = 8, - border = { top = true, right = true, bottom = true, left = true }, - borderColor = Color.new(1, 1, 1, 0.3), - }) - end - - -- Section 3: Interactive z-index demo - FlexLove.new({ - x = "2vw", - y = "53vh", - width = "96vw", - height = "3vh", - text = "Click to Bring to Front", - textSize = "2.5vh", - textColor = Color.new(0.9, 0.9, 0.9, 1), - }) - - local maxZ = 10 - - -- Create interactive boxes - for i = 1, 4 do - local box = FlexLove.new({ - x = (5 + (i - 1) * 22) .. "vw", - y = "58vh", - width = "20vw", - height = "20vh", - z = i, - backgroundColor = Color.new( - 0.4 + i * 0.1, - 0.5 + math.sin(i) * 0.2, - 0.7 - i * 0.1, - 1 - ), - text = "Box " .. i .. "\nClick me!", - textSize = "2.2vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - cornerRadius = 10, - }) - - -- Add click handler to bring to front - box.onEvent = function(element) - maxZ = maxZ + 1 - element.z = maxZ - element.text = "Box " .. i .. "\nZ: " .. element.z - end - end - - -- Info text - FlexLove.new({ - x = "2vw", - y = "82vh", - width = "96vw", - height = "14vh", - backgroundColor = Color.new(0.15, 0.15, 0.2, 1), - text = "Z-Index determines the stacking order of elements.\n" .. - "Higher values appear on top of lower values.\n" .. - "Click the boxes above to bring them to the front!", - textSize = "2vh", - textColor = Color.new(0.9, 0.9, 0.9, 1), - textAlign = enums.TextAlign.CENTER, - cornerRadius = 8, - }) -end - -function Lv.update(dt) - FlexLove.update(dt) -end - -function Lv.draw() - Lv.graphics.clear(0.05, 0.05, 0.08, 1) - FlexLove.draw() -end - -function Lv.resize(w, h) - FlexLove.resize(w, h) -end diff --git a/examples/13_comprehensive_demo.lua b/examples/13_comprehensive_demo.lua deleted file mode 100644 index 806c2ea..0000000 --- a/examples/13_comprehensive_demo.lua +++ /dev/null @@ -1,273 +0,0 @@ ---[[ - FlexLove Example 13: Comprehensive Demo - - This example combines multiple FlexLove features into a polished demo: - - Flex and grid layouts - - Themed components - - Animations - - Event handling - - Responsive design - - Run with: love /path/to/libs/examples/13_comprehensive_demo.lua -]] - -local Lv = love - -local FlexLove = require("../FlexLove") -local Color = FlexLove.Color -local Animation = FlexLove.Animation -local enums = FlexLove.enums - -function Lv.load() - FlexLove.init({ - baseScale = { width = 1920, height = 1080 }, - theme = "space" - }) - - -- Header - local header = FlexLove.new({ - x = 0, - y = 0, - width = "100vw", - height = "12vh", - positioning = enums.Positioning.FLEX, - flexDirection = enums.FlexDirection.HORIZONTAL, - justifyContent = enums.JustifyContent.SPACE_BETWEEN, - alignItems = enums.AlignItems.CENTER, - backgroundColor = Color.new(0.1, 0.1, 0.15, 1), - padding = { top = 10, right = 20, bottom = 10, left = 20 }, - border = { bottom = true }, - borderColor = Color.new(0.3, 0.3, 0.4, 1), - }) - - -- Logo/Title - FlexLove.new({ - parent = header, - width = "auto", - height = "auto", - text = "FlexLove Demo", - textSize = "4vh", - textColor = Color.new(0.8, 0.9, 1, 1), - }) - - -- Header buttons - local headerButtons = FlexLove.new({ - parent = header, - width = "auto", - height = "auto", - positioning = enums.Positioning.FLEX, - flexDirection = enums.FlexDirection.HORIZONTAL, - gap = 10, - }) - - local buttonNames = { "Home", "Features", "About" } - for _, name in ipairs(buttonNames) do - FlexLove.new({ - parent = headerButtons, - width = "8vw", - height = "6vh", - backgroundColor = Color.new(0.3, 0.4, 0.6, 1), - text = name, - textSize = "2vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - cornerRadius = 5, - themeComponent = "button", - }) - end - - -- Main content area - local mainContent = FlexLove.new({ - x = 0, - y = "12vh", - width = "100vw", - height = "88vh", - positioning = enums.Positioning.FLEX, - flexDirection = enums.FlexDirection.HORIZONTAL, - backgroundColor = Color.new(0.05, 0.05, 0.08, 1), - }) - - -- Sidebar - local sidebar = FlexLove.new({ - parent = mainContent, - width = "20vw", - height = "88vh", - positioning = enums.Positioning.FLEX, - flexDirection = enums.FlexDirection.VERTICAL, - backgroundColor = Color.new(0.08, 0.08, 0.12, 1), - padding = { top = 20, right = 10, bottom = 20, left = 10 }, - gap = 10, - border = { right = true }, - borderColor = Color.new(0.2, 0.2, 0.3, 1), - }) - - -- Sidebar menu items - local menuItems = { - { icon = "◆", label = "Dashboard" }, - { icon = "◇", label = "Analytics" }, - { icon = "○", label = "Settings" }, - { icon = "□", label = "Profile" }, - { icon = "△", label = "Help" }, - } - - for _, item in ipairs(menuItems) do - local menuButton = FlexLove.new({ - parent = sidebar, - width = "auto", - height = "7vh", - positioning = enums.Positioning.FLEX, - flexDirection = enums.FlexDirection.HORIZONTAL, - alignItems = enums.AlignItems.CENTER, - backgroundColor = Color.new(0.15, 0.15, 0.2, 1), - padding = { top = 10, right = 15, bottom = 10, left = 15 }, - cornerRadius = 5, - }) - - FlexLove.new({ - parent = menuButton, - width = "auto", - height = "auto", - text = item.icon .. " " .. item.label, - textSize = "2vh", - textColor = Color.new(0.9, 0.9, 0.9, 1), - }) - end - - -- Content panel - local contentPanel = FlexLove.new({ - parent = mainContent, - width = "80vw", - height = "88vh", - positioning = enums.Positioning.FLEX, - flexDirection = enums.FlexDirection.VERTICAL, - padding = { top = 20, right = 20, bottom = 20, left = 20 }, - gap = 15, - }) - - -- Welcome section - FlexLove.new({ - parent = contentPanel, - width = "auto", - height = "auto", - text = "Welcome to FlexLove!", - textSize = "3.5vh", - textColor = Color.new(1, 1, 1, 1), - }) - - -- Stats grid - local statsGrid = FlexLove.new({ - parent = contentPanel, - width = "auto", - height = "20vh", - positioning = enums.Positioning.GRID, - gridRows = 1, - gridColumns = 4, - columnGap = 15, - }) - - local stats = { - { label = "Projects", value = "24", color = Color.new(0.3, 0.6, 0.8, 1) }, - { label = "Users", value = "1.2K", color = Color.new(0.6, 0.3, 0.8, 1) }, - { label = "Revenue", value = "$45K", color = Color.new(0.8, 0.6, 0.3, 1) }, - { label = "Growth", value = "+12%", color = Color.new(0.3, 0.8, 0.6, 1) }, - } - - for _, stat in ipairs(stats) do - local statCard = FlexLove.new({ - parent = statsGrid, - positioning = enums.Positioning.FLEX, - flexDirection = enums.FlexDirection.VERTICAL, - justifyContent = enums.JustifyContent.CENTER, - alignItems = enums.AlignItems.CENTER, - backgroundColor = stat.color, - cornerRadius = 8, - padding = { top = 15, right = 15, bottom = 15, left = 15 }, - }) - - FlexLove.new({ - parent = statCard, - width = "auto", - height = "auto", - text = stat.value, - textSize = "4vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - }) - - FlexLove.new({ - parent = statCard, - width = "auto", - height = "auto", - text = stat.label, - textSize = "1.8vh", - textColor = Color.new(0.9, 0.9, 0.9, 1), - textAlign = enums.TextAlign.CENTER, - }) - end - - -- Feature cards - local cardsContainer = FlexLove.new({ - parent = contentPanel, - width = "auto", - height = "auto", - positioning = enums.Positioning.GRID, - gridRows = 2, - gridColumns = 3, - rowGap = 15, - columnGap = 15, - }) - - local features = { - "Flexbox Layout", - "Grid System", - "Theming", - "Animations", - "Events", - "Responsive" - } - - for i, feature in ipairs(features) do - local card = FlexLove.new({ - parent = cardsContainer, - positioning = enums.Positioning.FLEX, - justifyContent = enums.JustifyContent.CENTER, - alignItems = enums.AlignItems.CENTER, - backgroundColor = Color.new(0.15, 0.15, 0.2, 1), - cornerRadius = 10, - padding = { top = 20, right = 20, bottom = 20, left = 20 }, - }) - - FlexLove.new({ - parent = card, - width = "auto", - height = "auto", - text = feature, - textSize = "2.5vh", - textColor = Color.new(0.9, 0.9, 0.9, 1), - textAlign = enums.TextAlign.CENTER, - }) - - -- Add hover animation - card.onEvent = function(element) - local anim = Animation.new({ - duration = 0.2, - start = { opacity = 1 }, - final = { opacity = 0.8 }, - }) - anim:apply(element) - end - end -end - -function Lv.update(dt) - FlexLove.update(dt) -end - -function Lv.draw() - Lv.graphics.clear(0.05, 0.05, 0.08, 1) - FlexLove.draw() -end - -function Lv.resize(w, h) - FlexLove.resize(w, h) -end diff --git a/examples/14_drag_slider.lua b/examples/14_drag_slider.lua deleted file mode 100644 index 570306d..0000000 --- a/examples/14_drag_slider.lua +++ /dev/null @@ -1,305 +0,0 @@ ---[[ - FlexLove Example 14: Drag Event - Slider Implementation - - This example demonstrates how to use the new drag event to create - interactive sliders without any first-party slider component. - - Features demonstrated: - - Using drag events for continuous mouse tracking - - Converting mouse coordinates to element-relative positions - - Updating UI elements based on drag position - - Creating reusable slider components - - Run with: love /path/to/libs/examples/14_drag_slider.lua -]] - -local Lv = love - -local FlexLove = require("../FlexLove") -local Color = FlexLove.Color -local enums = FlexLove.enums - --- Slider state -local volume = 0.5 -- 0.0 to 1.0 -local brightness = 0.75 -- 0.0 to 1.0 -local temperature = 20 -- 0 to 40 (degrees) - --- UI elements -local volumeValueText -local brightnessValueText -local temperatureValueText -local volumeHandle -local brightnessHandle -local temperatureHandle - ---- Helper function to create a slider ----@param x string|number ----@param y string|number ----@param width string|number ----@param label string ----@param min number ----@param max number ----@param initialValue number ----@param onValueChange function ----@return table -- Returns { bg, handle, valueText } -local function createSlider(x, y, width, label, min, max, initialValue, onValueChange) - -- Container for the slider - local container = FlexLove.new({ - x = x, - y = y, - width = width, - height = "12vh", - positioning = enums.Positioning.FLEX, - flexDirection = enums.FlexDirection.VERTICAL, - gap = 5, - }) - - -- Label - FlexLove.new({ - parent = container, - height = "3vh", - text = label, - textSize = "2vh", - textColor = Color.new(0.9, 0.9, 0.9, 1), - }) - - -- Slider track background - local sliderBg = FlexLove.new({ - parent = container, - height = "4vh", - backgroundColor = Color.new(0.2, 0.2, 0.25, 1), - cornerRadius = 5, - positioning = enums.Positioning.RELATIVE, - }) - - -- Slider handle - local normalized = (initialValue - min) / (max - min) - local handle = FlexLove.new({ - parent = sliderBg, - x = (normalized * 95) .. "%", - y = "50%", - width = "5%", - height = "80%", - backgroundColor = Color.new(0.4, 0.6, 0.9, 1), - cornerRadius = 3, - positioning = enums.Positioning.ABSOLUTE, - -- Center the handle vertically - top = "10%", - }) - - -- Value display - local valueText = FlexLove.new({ - parent = container, - height = "3vh", - text = string.format("%.2f", initialValue), - textSize = "2vh", - textColor = Color.new(0.7, 0.8, 1, 1), - textAlign = enums.TextAlign.CENTER, - }) - - -- Make the background track interactive - sliderBg.onEvent = function(element, event) - if event.type == "press" or event.type == "drag" then - -- Get element bounds - local bg_x = element.x - local bg_width = element.width - - -- Calculate relative position (0 to 1) - local mouse_x = event.x - local relative_x = mouse_x - bg_x - local new_normalized = math.max(0, math.min(1, relative_x / bg_width)) - - -- Calculate actual value - local new_value = min + (new_normalized * (max - min)) - - -- Update handle position (use percentage for responsiveness) - handle.x = (new_normalized * 95) .. "%" - - -- Update value text - if max - min > 10 then - -- For larger ranges (like temperature), show integers - valueText.text = string.format("%d", new_value) - else - -- For smaller ranges (like 0-1), show decimals - valueText.text = string.format("%.2f", new_value) - end - - -- Call the value change callback - if onValueChange then - onValueChange(new_value) - end - - -- Re-layout to apply position changes - element:recalculateUnits(Lv.graphics.getWidth(), Lv.graphics.getHeight()) - end - end - - return { - container = container, - bg = sliderBg, - handle = handle, - valueText = valueText, - } -end - -function Lv.load() - FlexLove.init({ - baseScale = { width = 1920, height = 1080 }, - }) - - -- Title - FlexLove.new({ - x = "2vw", - y = "2vh", - width = "96vw", - height = "6vh", - text = "FlexLove Example 14: Drag Event - Slider Implementation", - textSize = "4vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - }) - - -- Subtitle - FlexLove.new({ - x = "2vw", - y = "9vh", - width = "96vw", - height = "3vh", - text = "Drag the sliders to change values - built using only the drag event primitive!", - textSize = "2vh", - textColor = Color.new(0.7, 0.7, 0.7, 1), - textAlign = enums.TextAlign.CENTER, - }) - - -- Volume Slider (0.0 - 1.0) - local volumeSlider = createSlider("10vw", "18vh", "80vw", "Volume (0.0 - 1.0)", 0.0, 1.0, volume, function(value) - volume = value - end) - volumeValueText = volumeSlider.valueText - volumeHandle = volumeSlider.handle - - -- Brightness Slider (0.0 - 1.0) - local brightnessSlider = createSlider("10vw", "35vh", "80vw", "Brightness (0.0 - 1.0)", 0.0, 1.0, brightness, function(value) - brightness = value - end) - brightnessValueText = brightnessSlider.valueText - brightnessHandle = brightnessSlider.handle - - -- Temperature Slider (0 - 40°C) - local temperatureSlider = createSlider("10vw", "52vh", "80vw", "Temperature (0 - 40°C)", 0, 40, temperature, function(value) - temperature = value - end) - temperatureValueText = temperatureSlider.valueText - temperatureHandle = temperatureSlider.handle - - -- Visual feedback section - FlexLove.new({ - x = "10vw", - y = "70vh", - width = "80vw", - height = "3vh", - text = "Visual Feedback:", - textSize = "2.5vh", - textColor = Color.new(1, 1, 1, 1), - }) - - -- Volume visualization - FlexLove.new({ - x = "10vw", - y = "75vh", - width = "25vw", - height = "20vh", - backgroundColor = Color.new(0.15, 0.15, 0.2, 1), - cornerRadius = 10, - border = { top = true, right = true, bottom = true, left = true }, - borderColor = Color.new(0.3, 0.3, 0.4, 1), - }) - - -- Brightness visualization - FlexLove.new({ - x = "37.5vw", - y = "75vh", - width = "25vw", - height = "20vh", - backgroundColor = Color.new(0.15, 0.15, 0.2, 1), - cornerRadius = 10, - border = { top = true, right = true, bottom = true, left = true }, - borderColor = Color.new(0.3, 0.3, 0.4, 1), - }) - - -- Temperature visualization - FlexLove.new({ - x = "65vw", - y = "75vh", - width = "25vw", - height = "20vh", - backgroundColor = Color.new(0.15, 0.15, 0.2, 1), - cornerRadius = 10, - border = { top = true, right = true, bottom = true, left = true }, - borderColor = Color.new(0.3, 0.3, 0.4, 1), - }) -end - -function Lv.update(dt) - FlexLove.update(dt) -end - -function Lv.draw() - Lv.graphics.clear(0.05, 0.05, 0.08, 1) - FlexLove.draw() - - -- Draw volume visualization (speaker icon with bars) - local volumeX = Lv.graphics.getWidth() * 0.10 + 20 - local volumeY = Lv.graphics.getHeight() * 0.75 + 30 - Lv.graphics.setColor(0.4, 0.6, 0.9, 1) - Lv.graphics.print("Volume:", volumeX, volumeY, 0, 2, 2) - - -- Volume bars - local barCount = 10 - for i = 1, barCount do - if i / barCount <= volume then - Lv.graphics.setColor(0.4, 0.8, 0.4, 1) - else - Lv.graphics.setColor(0.2, 0.2, 0.25, 1) - end - local barX = volumeX + 20 + (i - 1) * 30 - local barHeight = 20 + i * 5 - Lv.graphics.rectangle("fill", barX, volumeY + 60 - barHeight, 20, barHeight, 3) - end - - -- Draw brightness visualization (sun icon) - local brightnessX = Lv.graphics.getWidth() * 0.375 + 20 - local brightnessY = Lv.graphics.getHeight() * 0.75 + 30 - Lv.graphics.setColor(0.4, 0.6, 0.9, 1) - Lv.graphics.print("Brightness:", brightnessX, brightnessY, 0, 2, 2) - - -- Sun circle - Lv.graphics.setColor(1, 0.9, 0.3, brightness) - Lv.graphics.circle("fill", brightnessX + 150, brightnessY + 80, 30 * brightness + 10) - - -- Draw temperature visualization (thermometer) - local tempX = Lv.graphics.getWidth() * 0.65 + 20 - local tempY = Lv.graphics.getHeight() * 0.75 + 30 - Lv.graphics.setColor(0.4, 0.6, 0.9, 1) - Lv.graphics.print("Temperature:", tempX, tempY, 0, 2, 2) - - -- Thermometer - local tempNormalized = temperature / 40 - local tempColor = { - 1 - tempNormalized * 0.5, -- Red increases with temp - 0.3, - 1 - tempNormalized, -- Blue decreases with temp - } - Lv.graphics.setColor(tempColor[1], tempColor[2], tempColor[3], 1) - Lv.graphics.rectangle("fill", tempX + 100, tempY + 50, 40, 100 * tempNormalized, 5) - Lv.graphics.setColor(0.3, 0.3, 0.4, 1) - Lv.graphics.rectangle("line", tempX + 100, tempY + 50, 40, 100, 5) - - -- Temperature text - Lv.graphics.setColor(1, 1, 1, 1) - Lv.graphics.print(string.format("%.0f°C", temperature), tempX + 160, tempY + 90, 0, 2, 2) -end - -function Lv.resize(w, h) - FlexLove.resize(w, h) -end diff --git a/examples/15_scrollable_elements.lua b/examples/15_scrollable_elements.lua deleted file mode 100644 index 33e9315..0000000 --- a/examples/15_scrollable_elements.lua +++ /dev/null @@ -1,126 +0,0 @@ --- Example 15: Scrollable Elements --- Demonstrates scrollable containers with overflow detection and visual scrollbars - -local FlexLove = require("../FlexLove") -local Color = FlexLove.Color -local enums = FlexLove.enums -local Lv = love - -function Lv.load() - FlexLove.init({ - baseScale = { width = 1920, height = 1080 }, - }) - - -- Title - FlexLove.new({ - x = "2vw", - y = "2vh", - width = "96vw", - height = "6vh", - text = "FlexLove Example 15: Scrollable Elements", - textSize = "4vh", - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - }) - - -- Example 1: Vertical scroll with auto scrollbars - local verticalScroll = FlexLove.new({ - x = "5vw", - y = "12vh", - width = "25vw", - height = "35vh", - overflow = "auto", - backgroundColor = Color.new(0.15, 0.15, 0.2, 1), - cornerRadius = 8, - positioning = enums.Positioning.FLEX, - flexDirection = enums.FlexDirection.VERTICAL, - gap = 5, - padding = { top = 10, right = 10, bottom = 10, left = 10 }, - }) - - -- Add many items to create overflow - for i = 1, 20 do - FlexLove.new({ - parent = verticalScroll, - height = "5vh", - backgroundColor = Color.new(0.3 + (i % 3) * 0.1, 0.4, 0.6, 1), - cornerRadius = 4, - text = "Item " .. i, - textColor = Color.new(1, 1, 1, 1), - textAlign = enums.TextAlign.CENTER, - }) - end - - -- Example 2: Custom styled scrollbar - local customScroll = FlexLove.new({ - x = "35vw", - y = "12vh", - width = "60vw", - height = "35vh", - overflow = "auto", - backgroundColor = Color.new(0.1, 0.1, 0.15, 1), - cornerRadius = 8, - scrollbarWidth = 16, - scrollbarColor = Color.new(0.3, 0.6, 0.9, 1), - scrollbarTrackColor = Color.new(0.15, 0.15, 0.2, 0.8), - scrollbarRadius = 8, - positioning = enums.Positioning.FLEX, - flexDirection = enums.FlexDirection.VERTICAL, - gap = 10, - padding = { top = 15, right = 15, bottom = 15, left = 15 }, - }) - - -- Add content - for i = 1, 25 do - FlexLove.new({ - parent = customScroll, - height = "6vh", - backgroundColor = Color.new(0.2, 0.25, 0.3, 1), - cornerRadius = 6, - text = "Custom Scrollbar Item " .. i, - textColor = Color.new(0.9, 0.9, 1, 1), - textSize = "2vh", - }) - end - - -- Instructions - FlexLove.new({ - x = "5vw", - y = "52vh", - width = "90vw", - height = "40vh", - backgroundColor = Color.new(0.1, 0.15, 0.2, 0.9), - cornerRadius = 8, - padding = { top = 15, right = 15, bottom = 15, left = 15 }, - text = [[Instructions: -• Use mouse wheel to scroll elements under cursor -• Click and drag scrollbar thumb to scroll -• Click on scrollbar track to jump to position -• Scrollbars automatically appear when content overflows -• overflow="auto" shows scrollbars only when needed -• overflow="scroll" always shows scrollbars -• overflow="hidden" clips without scrollbars -• overflow="visible" shows all content (default) - -Scrollbar colors change on hover and when dragging!]], - textColor = Color.new(0.9, 0.9, 1, 1), - textSize = "2vh", - }) -end - -function Lv.update(dt) - FlexLove.update(dt) -end - -function Lv.draw() - love.graphics.clear(0.05, 0.05, 0.08, 1) - FlexLove.draw() -end - -function Lv.resize(w, h) - FlexLove.resize(w, h) -end - -function Lv.wheelmoved(x, y) - FlexLove.wheelmoved(x, y) -end diff --git a/examples/16-full-imput-demo.lua b/examples/16-full-imput-demo.lua deleted file mode 100644 index 1511de0..0000000 --- a/examples/16-full-imput-demo.lua +++ /dev/null @@ -1,123 +0,0 @@ ---[[ -InputFieldsDemo.lua -Simple input field demo - multiple fields to test all features -Uses retained mode - elements are created once and reused ---]] - -local FlexLove = require("../FlexLove") -local Element = FlexLove.Element -local Color = FlexLove.Color - -local InputFieldsDemo = {} - --- Elements (created once) -local elements = {} -local initialized = false - --- Initialize elements once -local function initialize() - if initialized then - return - end - initialized = true - elements.container = Element.new({ - x = 0, - y = 0, - padding = { horizontal = "5%", vertical = "5%" }, - width = love.graphics.getWidth(), - height = love.graphics.getHeight(), - flexDirection = "vertical", - positioning = "flex", - gap = 10, - }) - - -- Title - elements.title = Element.new({ - parent = elements.container, - width = 700, - height = 40, - text = "FlexLove Input Field Demo", - textSize = 28, - textColor = Color.new(1, 1, 1, 1), - z = 1000, - }) - - -- Input field 1 - Empty with placeholder - elements.inputField1 = Element.new({ - parent = elements.container, - width = 600, - height = 50, - editable = true, - text = "", - textSize = 18, - textColor = Color.new(1, 1, 1, 1), - backgroundColor = Color.new(0.2, 0.2, 0.3, 0.9), - cornerRadius = 8, - padding = { horizontal = 15, vertical = 12 }, - placeholder = "Type here... (empty field with placeholder)", - selectOnFocus = false, - multiline = true, - autoGrow = true, - z = 1000, - onTextChange = function(element, newText) - print("Field 1 changed:", newText) - end, - }) - - -- Input field 2 - Pre-filled with selectOnFocus - elements.inputField2 = Element.new({ - parent = elements.container, - width = 600, - height = 50, - editable = true, - text = "Pre-filled text", - textSize = 18, - textColor = Color.new(1, 1, 1, 1), - backgroundColor = Color.new(0.2, 0.3, 0.2, 0.9), - cornerRadius = 8, - padding = { horizontal = 15, vertical = 12 }, - placeholder = "This shouldn't show", - selectOnFocus = true, - z = 1000, - onTextChange = function(_, newText) - print("Field 2 changed:", newText) - end, - }) - - elements.inputField3 = Element.new({ - parent = elements.container, - width = 600, - height = 50, - editable = true, - text = "", - textSize = 18, - textColor = Color.new(1, 1, 1, 1), - backgroundColor = Color.new(0.3, 0.2, 0.2, 0.9), - cornerRadius = 8, - padding = { horizontal = 15, vertical = 12 }, - placeholder = "Max 20 characters", - maxLength = 20, - selectOnFocus = false, - z = 1000, - onTextChange = function(element, newText) - print("Field 3 changed:", newText) - end, - }) - - elements.instructions = Element.new({ - parent = elements.container, - width = 700, - height = 200, - text = "Instructions:\n• Click on a field to focus it\n• Type to enter text\n• Field 1: Empty with placeholder\n• Field 2: Pre-filled, selects all on focus\n• Field 3: Max 20 characters\n• Press ESC to unfocus\n• Use arrow keys to move cursor", - textSize = 14, - textColor = Color.new(0.8, 0.8, 0.8, 1), - z = 1000, - }) -end - --- Render function (just initializes if needed) -function InputFieldsDemo.render() - initialize() -end - -return InputFieldsDemo diff --git a/modules/Context.lua b/modules/Context.lua index ef81ac1..02a64b6 100644 --- a/modules/Context.lua +++ b/modules/Context.lua @@ -85,7 +85,11 @@ local function isPointInElement(element, x, y) local bw = element._borderBoxWidth or (element.width + element.padding.left + element.padding.right) local bh = element._borderBoxHeight or (element.height + element.padding.top + element.padding.bottom) - -- Walk up parent chain to check clipping and apply scroll offsets + -- Calculate scroll offset from parent chain + local scrollOffsetX = 0 + local scrollOffsetY = 0 + + -- Walk up parent chain to check clipping and accumulate scroll offsets local current = element.parent while current do local overflowX = current.overflowX or current.overflow @@ -101,12 +105,20 @@ local function isPointInElement(element, x, y) if x < parentX or x > parentX + parentW or y < parentY or y > parentY + parentH then return false -- Point is clipped by parent end + + -- Accumulate scroll offset + scrollOffsetX = scrollOffsetX + (current._scrollX or 0) + scrollOffsetY = scrollOffsetY + (current._scrollY or 0) end current = current.parent end - return x >= bx and x <= bx + bw and y >= by and y <= by + bh + -- Adjust mouse position by scroll offset for hit testing + local adjustedX = x + scrollOffsetX + local adjustedY = y + scrollOffsetY + + return adjustedX >= bx and adjustedX <= bx + bw and adjustedY >= by and adjustedY <= by + bh end --- Get the topmost element at a screen position diff --git a/modules/Element.lua b/modules/Element.lua index 084829e..eacc1e7 100644 --- a/modules/Element.lua +++ b/modules/Element.lua @@ -540,6 +540,7 @@ function Element.new(props) Grid = Grid, Units = Units, Context = Context, + ErrorHandler = ErrorHandler, }) self._layoutEngine:initialize(self) @@ -633,7 +634,10 @@ function Element.new(props) -- Pixel units self.textSize = value else - ErrorHandler.error("Element", "Unknown textSize unit: " .. unit) + ErrorHandler.error( + "Element", + string.format("Unknown textSize unit '%s'. Valid units: px, %%, vw, vh, ew, eh. Or use presets: xs, sm, md, lg, xl, xxl, 2xl, 3xl, 4xl", unit) + ) end else -- Validate pixel textSize value @@ -835,13 +839,18 @@ function Element.new(props) -- Re-resolve ew/eh textSize units now that width/height are set if props.textSize and type(props.textSize) == "string" then - local value, unit = Units.parse(props.textSize) - if unit == "ew" then - -- Element width relative (now that width is set) - self.textSize = (value / 100) * self.width - elseif unit == "eh" then - -- Element height relative (now that height is set) - self.textSize = (value / 100) * self.height + -- Check if it's a preset first (presets don't need re-resolution) + local presetValue, presetUnit = resolveTextSizePreset(props.textSize) + if not presetValue then + -- Not a preset, parse and check for ew/eh units + local value, unit = Units.parse(props.textSize) + if unit == "ew" then + -- Element width relative (now that width is set) + self.textSize = (value / 100) * self.width + elseif unit == "eh" then + -- Element height relative (now that height is set) + self.textSize = (value / 100) * self.height + end end end @@ -1026,7 +1035,7 @@ function Element.new(props) -- Absolute positioning is relative to parent's content area (padding box) local baseX = self.parent.x + self.parent.padding.left local baseY = self.parent.y + self.parent.padding.top - + -- Handle x position with units if props.x then if type(props.x) == "string" then @@ -1253,16 +1262,36 @@ function Element.new(props) -- Update the LayoutEngine with actual layout properties -- (it was initialized early with defaults for auto-sizing calculations) self._layoutEngine.positioning = self.positioning - if self.flexDirection then self._layoutEngine.flexDirection = self.flexDirection end - if self.flexWrap then self._layoutEngine.flexWrap = self.flexWrap end - if self.justifyContent then self._layoutEngine.justifyContent = self.justifyContent end - if self.alignItems then self._layoutEngine.alignItems = self.alignItems end - if self.alignContent then self._layoutEngine.alignContent = self.alignContent end - if self.gap then self._layoutEngine.gap = self.gap end - if self.gridRows then self._layoutEngine.gridRows = self.gridRows end - if self.gridColumns then self._layoutEngine.gridColumns = self.gridColumns end - if self.columnGap then self._layoutEngine.columnGap = self.columnGap end - if self.rowGap then self._layoutEngine.rowGap = self.rowGap end + if self.flexDirection then + self._layoutEngine.flexDirection = self.flexDirection + end + if self.flexWrap then + self._layoutEngine.flexWrap = self.flexWrap + end + if self.justifyContent then + self._layoutEngine.justifyContent = self.justifyContent + end + if self.alignItems then + self._layoutEngine.alignItems = self.alignItems + end + if self.alignContent then + self._layoutEngine.alignContent = self.alignContent + end + if self.gap then + self._layoutEngine.gap = self.gap + end + if self.gridRows then + self._layoutEngine.gridRows = self.gridRows + end + if self.gridColumns then + self._layoutEngine.gridColumns = self.gridColumns + end + if self.columnGap then + self._layoutEngine.columnGap = self.columnGap + end + if self.rowGap then + self._layoutEngine.rowGap = self.rowGap + end ---animation self.transform = props.transform or {} @@ -1285,6 +1314,7 @@ function Element.new(props) _scrollY = props._scrollY, }, { utils = utils, + Color = Color, }) self._scrollManager:initialize(self) @@ -1464,15 +1494,6 @@ function Element:_handleScrollbarRelease(button) return false end ---- Scroll to track click position (internal method used by ScrollManager) ----@param mouseX number ----@param mouseY number ----@param component string -- "vertical" or "horizontal" -function Element:_scrollToTrackPosition(mouseX, mouseY, component) - -- This method is now handled internally by ScrollManager - -- Keeping empty stub for backward compatibility -end - --- Handle mouse wheel scrolling (delegates to ScrollManager) ---@param x number -- Horizontal scroll amount ---@param y number -- Vertical scroll amount @@ -1794,10 +1815,11 @@ function Element:draw(backdropCanvas) self._renderer:drawText(self) -- Draw visual feedback when element is pressed (if it has an onEvent handler and highlight is not disabled) - if self.onEvent and not self.disableHighlight then + if self.onEvent and not self.disableHighlight and self._eventHandler then -- Check if any button is pressed local anyPressed = false - for _, pressed in pairs(self._pressed) do + local pressedState = self._eventHandler:getState()._pressed or {} + for _, pressed in pairs(pressedState) do if pressed then anyPressed = true break diff --git a/modules/LayoutEngine.lua b/modules/LayoutEngine.lua index 0b793d6..487ba5a 100644 --- a/modules/LayoutEngine.lua +++ b/modules/LayoutEngine.lua @@ -57,6 +57,7 @@ function LayoutEngine.new(props, deps) self._Grid = deps.Grid self._Units = deps.Units self._Context = deps.Context + self._ErrorHandler = deps.ErrorHandler self._Positioning = Positioning self._FlexDirection = FlexDirection self._JustifyContent = JustifyContent @@ -174,6 +175,22 @@ function LayoutEngine:layoutChildren() local isFlexChild = not (child.positioning == self._Positioning.ABSOLUTE and child._explicitlyAbsolute) if isFlexChild then table.insert(flexChildren, child) + + -- Warn if child uses percentage sizing but parent has autosizing + if self._ErrorHandler then + if child.units and child.units.width then + if child.units.width.unit == "%" and self.element.autosizing and self.element.autosizing.width then + self._ErrorHandler.warn("LayoutEngine", + string.format("Child '%s' uses percentage width but parent has auto-sizing enabled. This may cause unexpected results", child.id or "unnamed")) + end + end + if child.units and child.units.height then + if child.units.height.unit == "%" and self.element.autosizing and self.element.autosizing.height then + self._ErrorHandler.warn("LayoutEngine", + string.format("Child '%s' uses percentage height but parent has auto-sizing enabled. This may cause unexpected results", child.id or "unnamed")) + end + end + end end end diff --git a/modules/Units.lua b/modules/Units.lua index 220f676..faa4bc0 100644 --- a/modules/Units.lua +++ b/modules/Units.lua @@ -1,6 +1,7 @@ local Units = {} local Context = nil +local ErrorHandler = nil --- Initialize Units module with Context dependency ---@param context table The Context module @@ -8,6 +9,12 @@ function Units.initialize(context) Context = context end +--- Initialize ErrorHandler dependency +---@param errorHandler table The ErrorHandler module +function Units.initializeErrorHandler(errorHandler) + ErrorHandler = errorHandler +end + ---@param value string|number ---@return number, string -- Returns numeric value and unit type ("px", "%", "vw", "vh") function Units.parse(value) @@ -16,20 +23,34 @@ function Units.parse(value) end if type(value) ~= "string" then - -- Fallback to 0px for invalid types + if ErrorHandler then + ErrorHandler.error("Units", string.format("Invalid unit value type. Expected string or number, got %s", type(value))) + end + return 0, "px" + end + + -- Check for invalid format (space between number and unit) + if value:match("%d%s+%a") then + if ErrorHandler then + ErrorHandler.error("Units", string.format("Invalid unit string '%s' (contains space). Use format like '50px' or '50%%'", value)) + end return 0, "px" end -- Match number followed by optional unit local numStr, unit = value:match("^([%-]?[%d%.]+)(.*)$") if not numStr then - -- Fallback to 0px for invalid format + if ErrorHandler then + ErrorHandler.error("Units", string.format("Invalid unit format '%s'. Expected format: number + unit (e.g., '50px', '10%%', '2vw')", value)) + end return 0, "px" end local num = tonumber(numStr) if not num then - -- Fallback to 0px for invalid numeric value + if ErrorHandler then + ErrorHandler.error("Units", string.format("Invalid numeric value in '%s'", value)) + end return 0, "px" end @@ -40,6 +61,9 @@ function Units.parse(value) local validUnits = { px = true, ["%"] = true, vw = true, vh = true, ew = true, eh = true } if not validUnits[unit] then + if ErrorHandler then + ErrorHandler.error("Units", string.format("Unknown unit '%s' in '%s'. Valid units: px, %%, vw, vh, ew, eh", unit, value)) + end return num, "px" end @@ -59,7 +83,11 @@ function Units.resolve(value, unit, viewportWidth, viewportHeight, parentSize) return value elseif unit == "%" then if not parentSize then - error(formatError("Units", "Percentage units require parent dimension")) + if ErrorHandler then + ErrorHandler.error("Units", "Percentage units require parent dimension. Element has no parent or parent dimension not available") + else + error("Percentage units require parent dimension") + end end return (value / 100) * parentSize elseif unit == "vw" then @@ -67,7 +95,11 @@ function Units.resolve(value, unit, viewportWidth, viewportHeight, parentSize) elseif unit == "vh" then return (value / 100) * viewportHeight else - error(formatError("Units", string.format("Unknown unit type: '%s'. Valid units: px, %%, vw, vh, ew, eh", unit))) + if ErrorHandler then + ErrorHandler.error("Units", string.format("Unknown unit '%s'. Valid units: px, %%, vw, vh, ew, eh", unit)) + else + error(string.format("Unknown unit type: '%s'", unit)) + end end end