immediate mode scroll regression fixed

This commit is contained in:
Michael Freno
2025-11-13 22:33:53 -05:00
parent 7ae09ec690
commit 93af33825d
21 changed files with 192 additions and 3681 deletions

View File

@@ -9,6 +9,7 @@ local utils = req("utils")
local Units = req("Units") local Units = req("Units")
local Context = req("Context") local Context = req("Context")
local StateManager = req("StateManager") local StateManager = req("StateManager")
local ErrorHandler = req("ErrorHandler")
---@type Element ---@type Element
local Element = req("Element") local Element = req("Element")
@@ -26,6 +27,7 @@ local flexlove = Context
-- Initialize Units module with Context dependency -- Initialize Units module with Context dependency
Units.initialize(Context) Units.initialize(Context)
Units.initializeErrorHandler(ErrorHandler)
-- Add version and metadata -- Add version and metadata
flexlove._VERSION = "0.1.0" flexlove._VERSION = "0.1.0"
@@ -480,10 +482,10 @@ function flexlove.keypressed(key, scancode, isrepeat)
end end
end end
function flexlove.wheelmoved(x, y) function flexlove.wheelmoved(dx, dy)
local mx, my = love.mouse.getPosition() local mx, my = love.mouse.getPosition()
local function findScrollableAtPosition(elements, mx, my) local function findScrollableAtPosition(elements, x, y)
for i = #elements, 1, -1 do for i = #elements, 1, -1 do
local element = elements[i] 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 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) 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 if #element.children > 0 then
local childResult = findScrollableAtPosition(element.children, mx, my) local childResult = findScrollableAtPosition(element.children, x, y)
if childResult then if childResult then
return childResult return childResult
end end
@@ -521,12 +523,71 @@ function flexlove.wheelmoved(x, y)
local bw = element._borderBoxWidth or (element.width + element.padding.left + element.padding.right) 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) 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 -- Calculate scroll offset from parent chain
local overflowX = element.overflowX or element.overflow local scrollOffsetX = 0
local overflowY = element.overflowY or element.overflow local scrollOffsetY = 0
if (overflowX == "scroll" or overflowX == "auto" or overflowY == "scroll" or overflowY == "auto") and (element._overflowX or element._overflowY) then local current = element.parent
element:_handleWheelScroll(x, y) while current do
return 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 end
end end
@@ -534,7 +595,7 @@ function flexlove.wheelmoved(x, y)
-- In retained mode, use the old tree traversal method -- In retained mode, use the old tree traversal method
local scrollableElement = findScrollableAtPosition(flexlove.topElements, mx, my) local scrollableElement = findScrollableAtPosition(flexlove.topElements, mx, my)
if scrollableElement then if scrollableElement then
scrollableElement:_handleWheelScroll(x, y) scrollableElement:_handleWheelScroll(dx, dy)
end end
end end
end end

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -85,7 +85,11 @@ local function isPointInElement(element, x, y)
local bw = element._borderBoxWidth or (element.width + element.padding.left + element.padding.right) 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) 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 local current = element.parent
while current do while current do
local overflowX = current.overflowX or current.overflow 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 if x < parentX or x > parentX + parentW or y < parentY or y > parentY + parentH then
return false -- Point is clipped by parent return false -- Point is clipped by parent
end end
-- Accumulate scroll offset
scrollOffsetX = scrollOffsetX + (current._scrollX or 0)
scrollOffsetY = scrollOffsetY + (current._scrollY or 0)
end end
current = current.parent current = current.parent
end 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 end
--- Get the topmost element at a screen position --- Get the topmost element at a screen position

View File

@@ -540,6 +540,7 @@ function Element.new(props)
Grid = Grid, Grid = Grid,
Units = Units, Units = Units,
Context = Context, Context = Context,
ErrorHandler = ErrorHandler,
}) })
self._layoutEngine:initialize(self) self._layoutEngine:initialize(self)
@@ -633,7 +634,10 @@ function Element.new(props)
-- Pixel units -- Pixel units
self.textSize = value self.textSize = value
else 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 end
else else
-- Validate pixel textSize value -- Validate pixel textSize value
@@ -835,13 +839,18 @@ function Element.new(props)
-- Re-resolve ew/eh textSize units now that width/height are set -- Re-resolve ew/eh textSize units now that width/height are set
if props.textSize and type(props.textSize) == "string" then if props.textSize and type(props.textSize) == "string" then
local value, unit = Units.parse(props.textSize) -- Check if it's a preset first (presets don't need re-resolution)
if unit == "ew" then local presetValue, presetUnit = resolveTextSizePreset(props.textSize)
-- Element width relative (now that width is set) if not presetValue then
self.textSize = (value / 100) * self.width -- Not a preset, parse and check for ew/eh units
elseif unit == "eh" then local value, unit = Units.parse(props.textSize)
-- Element height relative (now that height is set) if unit == "ew" then
self.textSize = (value / 100) * self.height -- 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
end end
@@ -1253,16 +1262,36 @@ function Element.new(props)
-- Update the LayoutEngine with actual layout properties -- Update the LayoutEngine with actual layout properties
-- (it was initialized early with defaults for auto-sizing calculations) -- (it was initialized early with defaults for auto-sizing calculations)
self._layoutEngine.positioning = self.positioning self._layoutEngine.positioning = self.positioning
if self.flexDirection then self._layoutEngine.flexDirection = self.flexDirection end if self.flexDirection then
if self.flexWrap then self._layoutEngine.flexWrap = self.flexWrap end self._layoutEngine.flexDirection = self.flexDirection
if self.justifyContent then self._layoutEngine.justifyContent = self.justifyContent end end
if self.alignItems then self._layoutEngine.alignItems = self.alignItems end if self.flexWrap then
if self.alignContent then self._layoutEngine.alignContent = self.alignContent end self._layoutEngine.flexWrap = self.flexWrap
if self.gap then self._layoutEngine.gap = self.gap end end
if self.gridRows then self._layoutEngine.gridRows = self.gridRows end if self.justifyContent then
if self.gridColumns then self._layoutEngine.gridColumns = self.gridColumns end self._layoutEngine.justifyContent = self.justifyContent
if self.columnGap then self._layoutEngine.columnGap = self.columnGap end end
if self.rowGap then self._layoutEngine.rowGap = self.rowGap 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 ---animation
self.transform = props.transform or {} self.transform = props.transform or {}
@@ -1285,6 +1314,7 @@ function Element.new(props)
_scrollY = props._scrollY, _scrollY = props._scrollY,
}, { }, {
utils = utils, utils = utils,
Color = Color,
}) })
self._scrollManager:initialize(self) self._scrollManager:initialize(self)
@@ -1464,15 +1494,6 @@ function Element:_handleScrollbarRelease(button)
return false return false
end 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) --- Handle mouse wheel scrolling (delegates to ScrollManager)
---@param x number -- Horizontal scroll amount ---@param x number -- Horizontal scroll amount
---@param y number -- Vertical scroll amount ---@param y number -- Vertical scroll amount
@@ -1794,10 +1815,11 @@ function Element:draw(backdropCanvas)
self._renderer:drawText(self) self._renderer:drawText(self)
-- Draw visual feedback when element is pressed (if it has an onEvent handler and highlight is not disabled) -- 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 -- Check if any button is pressed
local anyPressed = false 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 if pressed then
anyPressed = true anyPressed = true
break break

View File

@@ -57,6 +57,7 @@ function LayoutEngine.new(props, deps)
self._Grid = deps.Grid self._Grid = deps.Grid
self._Units = deps.Units self._Units = deps.Units
self._Context = deps.Context self._Context = deps.Context
self._ErrorHandler = deps.ErrorHandler
self._Positioning = Positioning self._Positioning = Positioning
self._FlexDirection = FlexDirection self._FlexDirection = FlexDirection
self._JustifyContent = JustifyContent self._JustifyContent = JustifyContent
@@ -174,6 +175,22 @@ function LayoutEngine:layoutChildren()
local isFlexChild = not (child.positioning == self._Positioning.ABSOLUTE and child._explicitlyAbsolute) local isFlexChild = not (child.positioning == self._Positioning.ABSOLUTE and child._explicitlyAbsolute)
if isFlexChild then if isFlexChild then
table.insert(flexChildren, child) 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
end end

View File

@@ -1,6 +1,7 @@
local Units = {} local Units = {}
local Context = nil local Context = nil
local ErrorHandler = nil
--- Initialize Units module with Context dependency --- Initialize Units module with Context dependency
---@param context table The Context module ---@param context table The Context module
@@ -8,6 +9,12 @@ function Units.initialize(context)
Context = context Context = context
end end
--- Initialize ErrorHandler dependency
---@param errorHandler table The ErrorHandler module
function Units.initializeErrorHandler(errorHandler)
ErrorHandler = errorHandler
end
---@param value string|number ---@param value string|number
---@return number, string -- Returns numeric value and unit type ("px", "%", "vw", "vh") ---@return number, string -- Returns numeric value and unit type ("px", "%", "vw", "vh")
function Units.parse(value) function Units.parse(value)
@@ -16,20 +23,34 @@ function Units.parse(value)
end end
if type(value) ~= "string" then 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" return 0, "px"
end end
-- Match number followed by optional unit -- Match number followed by optional unit
local numStr, unit = value:match("^([%-]?[%d%.]+)(.*)$") local numStr, unit = value:match("^([%-]?[%d%.]+)(.*)$")
if not numStr then 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" return 0, "px"
end end
local num = tonumber(numStr) local num = tonumber(numStr)
if not num then 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" return 0, "px"
end end
@@ -40,6 +61,9 @@ function Units.parse(value)
local validUnits = { px = true, ["%"] = true, vw = true, vh = true, ew = true, eh = true } local validUnits = { px = true, ["%"] = true, vw = true, vh = true, ew = true, eh = true }
if not validUnits[unit] then 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" return num, "px"
end end
@@ -59,7 +83,11 @@ function Units.resolve(value, unit, viewportWidth, viewportHeight, parentSize)
return value return value
elseif unit == "%" then elseif unit == "%" then
if not parentSize 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 end
return (value / 100) * parentSize return (value / 100) * parentSize
elseif unit == "vw" then elseif unit == "vw" then
@@ -67,7 +95,11 @@ function Units.resolve(value, unit, viewportWidth, viewportHeight, parentSize)
elseif unit == "vh" then elseif unit == "vh" then
return (value / 100) * viewportHeight return (value / 100) * viewportHeight
else 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
end end