From 72b70b164c74758bb7bf8f101c19cd0769812092 Mon Sep 17 00:00:00 2001 From: Cruor Date: Fri, 12 Aug 2022 14:33:40 +0200 Subject: [PATCH] Added file picker dialog to path fields Thanks to Flagpole1up for the folder icons Small themes cleanup, default theme name is now in a varaible and currentTheme is the actuall theme object, not just the name --- src/ui/assets/icons/folder-16.png | Bin 0 -> 257 bytes src/ui/assets/icons/folder-24.png | Bin 0 -> 288 bytes src/ui/forms/fields/path.lua | 71 ++++++++++++++++++++++- src/ui/themes.lua | 3 +- src/ui/ui_device.lua | 4 +- src/ui/utils/icons.lua | 93 ++++++++++++++++++++++++++++++ 6 files changed, 167 insertions(+), 4 deletions(-) create mode 100644 src/ui/assets/icons/folder-16.png create mode 100644 src/ui/assets/icons/folder-24.png create mode 100644 src/ui/utils/icons.lua diff --git a/src/ui/assets/icons/folder-16.png b/src/ui/assets/icons/folder-16.png new file mode 100644 index 0000000000000000000000000000000000000000..64422d9de0cf67041f5e8d476d1c68aee7874a50 GIT binary patch literal 257 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJV{wqX6T`Z5GB1G~mUKs7M+SzC z{oH>NS%G}%0G|+7O$LU)6B+)Wim6s$Fa+vjU{GgZPy)&_F#KF`A__=xmIV0)|AzvG zVE+mskYIsFWHAE+-(e7DJf6QI1t=Kh>Ealo5ggkWD0V=B<8XuJ^S}Ok*kVM%xNb!1@J z*w6hZkrl|74)6(a)ns7!JCWi4shDa7215o04F(2v1_mXdECa*O6(^#A6lY10U+{k@ zUhYo1tGpFuIITV&s!Ce8cmg+%^a+tYuY2blW8pTRB<5sm z)StxCUi`noLqni(Mw((1yW7M!NqrB3eoVSBV?(@V>guiUcI&Q@{Hv$*uj?A$=Q56X U{@$tmKu0imy85}Sb4q9e07-&lc>n+a literal 0 HcmV?d00001 diff --git a/src/ui/forms/fields/path.lua b/src/ui/forms/fields/path.lua index 9bd2e1e1..8ddb1c8c 100644 --- a/src/ui/forms/fields/path.lua +++ b/src/ui/forms/fields/path.lua @@ -1,12 +1,54 @@ +local ui = require("ui") +local uiElements = require("ui.elements") +local uiUtils = require("ui.utils") + local utils = require("utils") local mods = require("mods") local loadedState = require("loaded_state") local stringField = require("ui.forms.fields.string") +local iconUtils = require("ui.utils.icons") +local fileLocations = require("file_locations") local pathField = {} pathField.fieldType = "path" +local function openFileDialog(textField, options) + local relativeToMod = options.relativeToMod + local allowedExtensions = options.allowedExtensions + + local filter + local startingPath = fileLocations.getCelesteDir() + + if allowedExtensions then + filter = table.concat(allowedExtensions, ",") + end + + if relativeToMod ~= false then + local modPath = mods.getFilenameModPath(loadedState.filename) + + if not modPath then + return false + end + + startingPath = modPath + end + + utils.openDialog(startingPath, filter, function(filename) + if relativeToMod ~= false then + local modPath = mods.getFilenameModPath(filename) + + if not modPath then + return false + end + + filename = string.sub(filename, #modPath + 2) + end + + textField:setText(filename) + end) +end + function pathField.getElement(name, value, options) -- Add extra options and pass it onto string field @@ -63,7 +105,34 @@ function pathField.getElement(name, value, options) return true end - return stringField.getElement(name, value, options) + local stringElement = stringField.getElement(name, value, options) + local textfield = stringElement.field + + if textfield.height == -1 then + textfield:layout() + end + + local iconMaxSize = textfield.label.height + local parentHeight = textfield.height + local folderIcon, iconSize = iconUtils.getIcon("folder", iconMaxSize) + + if folderIcon then + local centerOffset = math.floor((parentHeight - iconSize) / 2) + local folderImage = uiElements.image(folderIcon):with(uiUtils.rightbound(0)):with(uiUtils.at(0, centerOffset)) + + folderImage.interactive = 1 + folderImage:hook({ + onClick = function(orig, self) + orig(self) + + openFileDialog(textfield, options) + end + }) + + textfield:addChild(folderImage) + end + + return stringElement end return pathField \ No newline at end of file diff --git a/src/ui/themes.lua b/src/ui/themes.lua index 7209f37c..26ec3f57 100644 --- a/src/ui/themes.lua +++ b/src/ui/themes.lua @@ -8,6 +8,7 @@ local themes = {} themes.themes = {} themes.currentTheme = nil +themes.defaultThemeName = "dark" function themes.unloadThemes() themes.themes = {} @@ -75,7 +76,7 @@ end function themes.useTheme(name) if name and themes.themes[name] then - themes.currentTheme = name + themes.currentTheme = themes.themes[name] themer.apply(themes.themes[name]) diff --git a/src/ui/ui_device.lua b/src/ui/ui_device.lua index 6e93b048..9b5b34ec 100644 --- a/src/ui/ui_device.lua +++ b/src/ui/ui_device.lua @@ -35,7 +35,7 @@ function debugUtils.reloadUI() themes.unloadThemes() themes.loadInternalThemes() themes.loadExternalThemes() - themes.useTheme(themes.currentTheme) + themes.useTheme(themes.currentTheme.name) uiRoot.updateWindows(windows.getLoadedWindows()) @@ -62,7 +62,7 @@ function ui.initializeDevice() local appliedTheme = themes.useTheme(configTheme) if not appliedTheme then - themes.useTheme("dark") + themes.useTheme(themes.defaultThemeName) end end diff --git a/src/ui/utils/icons.lua b/src/ui/utils/icons.lua new file mode 100644 index 00000000..5a0b58c1 --- /dev/null +++ b/src/ui/utils/icons.lua @@ -0,0 +1,93 @@ +local themes = require("ui.themes") +local utils = require("utils") + +local iconUtils = {} + +local iconSizes = {64, 32, 24, 16} +local iconCache = {} + +local previousThemeName = themes.defaultThemeName + +function iconUtils.clearCache(name) + if name then + for _, size in ipairs(iconSizes) do + local cacheKey = string.format("%s-%s", name, size) + + iconCache[cacheKey] = nil + end + + else + iconCache = {} + end +end + +function iconUtils.getBestSize(maxSize) + for _, size in ipairs(iconSizes) do + if size <= maxSize then + return size + end + end +end + +function iconUtils.getIcon(name, maxSize, allowCustom) + local currentTheme = themes.currentTheme + + -- Invalidate all icons if theme has changed + if currentTheme.name ~= previousThemeName then + iconUtils.clearCache() + + previousThemeName = currentTheme.name + end + + local targetSize = iconUtils.getBestSize(maxSize) + local cacheKey = string.format("%s-%s", name, targetSize) + + if iconCache[cacheKey] then + return unpack(iconCache[cacheKey]) + end + + local iconsPath = "ui/assets/icons/" + + if currentTheme and currentTheme.iconsPath then + if allowCustom ~= false then + iconsPath = currentTheme.iconsPath + end + end + + -- Add image to cache for all sizes that fit + local image + local actualSize + local relevantSizes = {} + + for _, size in ipairs(iconSizes) do + if size <= maxSize then + table.insert(relevantSizes, size) + + local path = utils.joinpath(iconsPath, string.format("%s-%s.png", name, size)) + local fileInfo = love.filesystem.getInfo(path) or utils.pathAttributes(path) + + if fileInfo then + image = love.graphics.newImage(path) + actualSize = size + + break + end + end + end + + if image then + for _, size in ipairs(relevantSizes) do + cacheKey = string.format("%s-%s", name, size) + iconCache[cacheKey] = {image, actualSize} + end + + return image, actualSize + end + + -- Fallback to default theme + if allowCustom ~= false then + return iconUtils.getIcon(name, maxSize, false) + end +end + +return iconUtils \ No newline at end of file