4.3 KiB
local VisualElement = require("elements/VisualElement") local List = require("elements/List") local tHex = require("libraries/colorHex")
---@class Dropdown : List local Dropdown = setmetatable({}, List) Dropdown.__index = Dropdown
Dropdown.defineProperty(Dropdown, "isOpen", {default = false, type = "boolean", canTriggerRender = true}) Dropdown.defineProperty(Dropdown, "dropdownHeight", {default = 5, type = "number"}) Dropdown.defineProperty(Dropdown, "selectedText", {default = "", type = "string"}) Dropdown.defineProperty(Dropdown, "dropSymbol", {default = "\31", type = "string"}) -- ▼ Symbol
function Dropdown.new() local self = setmetatable({}, Dropdown):__init() self.set("width", 16) self.set("height", 1) self.set("z", 8) return self end
function Dropdown:init(props, basalt) List.init(self, props, basalt) self.set("type", "Dropdown") end
function Dropdown:mouse_click(button, x, y) if not VisualElement.mouse_click(self, button, x, y) then return false end
local relX, relY = self:getRelativePosition(x, y)
if relY == 1 then -- Klick auf Header
self.set("isOpen", not self.get("isOpen"))
if not self.get("isOpen") then
self.set("height", 1)
else
self.set("height", 1 + math.min(self.get("dropdownHeight"), #self.get("items")))
end
return true
elseif self.get("isOpen") and relY > 1 then
-- Offset für die Liste korrigieren (relY - 1 wegen Header)
local index = relY - 1 + self.get("offset")
local items = self.get("items")
if index <= #items then
local item = items[index]
if type(item) == "table" and item.separator then
return false
end
self.set("selectedIndex", index)
self.set("isOpen", false)
self.set("height", 1)
if type(item) == "table" and item.callback then
item.callback(self)
end
self:fireEvent("select", index, item)
return true
end
end
return false
end
function Dropdown:render() VisualElement.render(self)
-- Header rendern
local text = self.get("selectedText")
if #text == 0 and self.get("selectedIndex") > 0 then
local item = self.get("items")[self.get("selectedIndex")]
text = type(item) == "table" and item.text or tostring(item)
end
self:blit(1, 1, text .. string.rep(" ", self.get("width") - #text - 1) .. (self.get("isOpen") and "\31" or "\17"),
string.rep(tHex[self.get("foreground")], self.get("width")),
string.rep(tHex[self.get("background")], self.get("width")))
-- Items nur rendern wenn offen
if self.get("isOpen") then
local items = self.get("items")
local offset = self.get("offset")
local selected = self.get("selectedIndex")
local width = self.get("width")
-- Liste ab Zeile 2 rendern (unterhalb des Headers)
for i = 2, self.get("height") do
local itemIndex = i - 1 + offset -- -1 wegen Header
local item = items[itemIndex]
if item then
if type(item) == "table" and item.separator then
local separatorChar = (item.text or "-"):sub(1,1)
local separatorText = string.rep(separatorChar, width)
local fg = item.foreground or self.get("foreground")
local bg = item.background or self.get("background")
self:textBg(1, i, string.rep(" ", width), bg)
self:textFg(1, i, separatorText, fg)
else
local itemText = type(item) == "table" and item.text or tostring(item)
local isSelected = itemIndex == selected
local bg = isSelected and
(item.selectedBackground or self.get("selectedColor")) or
(item.background or self.get("background"))
local fg = isSelected and
(item.selectedForeground or colors.white) or
(item.foreground or self.get("foreground"))
self:textBg(1, i, string.rep(" ", width), bg)
self:textFg(1, i, itemText, fg)
end
end
end
end
end
return Dropdown