Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
399b8c0
Create a separate file for ThemePreferencesDialog
thkwznk Jan 28, 2024
8da9845
No longer overwrite passed theme in ThemePreferencesDialog
thkwznk Jan 28, 2024
2de1988
Reconnect simple saving to the new dialog
thkwznk Jan 28, 2024
e5ee769
Reintroduce changing modes and cursor colors
thkwznk Jan 28, 2024
9fc5f40
Save theme parameters
thkwznk Jan 28, 2024
c0ce480
Delete duplicate code
thkwznk Jan 28, 2024
ef7b048
Refactor and clean up
thkwznk Jan 28, 2024
fa95cee
Minor performance improvement when saving or applying themes
thkwznk Jan 28, 2024
6502441
Reintroduce initial dialog size
thkwznk Jan 28, 2024
e136adc
Minor refactor
thkwznk Jan 29, 2024
4a9cf5a
Refactor all dialogs out of ThemeManager
thkwznk Jan 29, 2024
7630128
Refactor logic for refreshing the theme into a separate file
thkwznk Jan 31, 2024
a30ef4f
Refactor FontConfigurationDialog to a separate file
thkwznk Jan 31, 2024
7df2cc4
Fix saving the current theme
thkwznk Jan 31, 2024
e18fd1a
Move the Font configuration to its own menu option
thkwznk Jan 31, 2024
7043b55
Rename the dialog to Font Preferences
thkwznk Jan 31, 2024
95e17aa
Move the "Reset to Default" option to the main dialog window
thkwznk Jan 31, 2024
8f74825
Fix broken replacing of semi-transparent template colors
thkwznk Feb 1, 2024
f522da4
Preload the theme sheet template file to improve performance
thkwznk Feb 1, 2024
fe2b7e5
Correctly size the Theme Preferences window
thkwznk Feb 1, 2024
d066652
Restore Theme Preferences dialog position after closing Load Configur…
thkwznk Feb 4, 2024
f279062
Encapsulate file access functions
thkwznk Feb 4, 2024
750340e
Refactor plugin preferences use
thkwznk Feb 4, 2024
d5d5487
Change user screen & UI scaling settings to correctly display vector …
thkwznk Feb 4, 2024
15c886f
Add "Save As" button for the Theme configuration
thkwznk Feb 4, 2024
f03575c
Add "Outline" color and support backwards compatibility of themes
thkwznk Feb 9, 2024
acc5a9b
Add "Title Bar" color to the Window section
thkwznk Feb 10, 2024
3a3f568
Load the template image on the first apply and not on start
thkwznk Feb 10, 2024
a5820d4
Update ROADMAP.md for Theme Preferences
thkwznk Feb 10, 2024
5e9aa1f
Update ROADMAP.md for Theme Preferences
thkwznk Feb 10, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 16 additions & 8 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,29 @@ Update v1.0.3.

Unreleased:

- ...
- [Improvement] Major performance improvement when applying theme preferences
- [Improvement] Move the Font configuration to it's own menu option under View > Font Preferences...
- [Improvement] Move the "Reset to Default" option to the main Theme Preferences dialog window
- [Improvement] Change user screen & UI scaling settings to correctly display vector fonts
- [Improvement] Add "Save As" button for the Theme configuration
- [Feature] Add "Outline" color
- [Feature] Add "Title Bar" Window color

Update v2.0.0:
Update v1.0.7:

- [Test-Feature] Tint Mode where you can only edit the Tab color + optional underglow
- [Improvement] A new color (set) - Window Title Bar
- [Improvement] Read font names from TTF files
- [Improvement] Rework the dialogs and menu options
- [Improvement] Update template with new elements for 1.3 and check for compatibility with 1.2

Future:
Update v1.0.8:

- [Fix] Make the title bar change it's height with font size

Update v2.0.0:

- [Improvement] Read font names from TTF files
- [Feature] Add a Dark theme template
- [Feature] [Blocked] Separate "field_background" when Aseprite fixes the menu shadow
- [Feature] [Blocked] Add separate color for Tooltip Text (Tooltip Section?) - currently it doesn't work due to a bug
- [Feature] Generating a theme from the current color palette
- [Refactor] Add a Default model next to Template - Template is a template, default is default

## FX

Expand Down
37 changes: 33 additions & 4 deletions Theme Preferences/Base64Encoder.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
local CODE_VERSION = 1
local Template = dofile("./Template.lua")()

local CODE_VERSION = 2
local START_CHARACTER = "<"
local LAST_CHARACTER = ">"
local SPLIT_CHARACTER = ":"
Expand Down Expand Up @@ -41,7 +43,14 @@ local Base64ThemeEncoder = {
"editor_cursor", --
"editor_cursor_shadow", --
"editor_cursor_outline", --
"editor_icons" --
"editor_icons", --
-- Outline
"outline", --
-- Window Title Bar
"window_title_bar_corner_highlight", --
"window_title_bar_highlight", --
"window_title_bar_background", --
"window_title_bar_shadow"
}
}

Expand Down Expand Up @@ -149,7 +158,9 @@ function Base64ThemeEncoder:EncodeColors(colors)
local result = ""

for _, id in ipairs(self.colorIds) do
result = result .. self:EncodeColor(colors[id])
result = result ..
self:EncodeColor(
colors[id] or self:GetDefaultColor(id, colors))
end

return result
Expand Down Expand Up @@ -228,7 +239,9 @@ function Base64ThemeEncoder:DecodeColors(version, encodedColors)
end

local colors = {}
for i, id in ipairs(self.colorIds) do colors[id] = decodedColors[i] end
for i, id in ipairs(self.colorIds) do
colors[id] = decodedColors[i] or self:GetDefaultColor(id, colors)
end

return colors
end
Expand All @@ -251,4 +264,20 @@ function Base64ThemeEncoder:DecodeName(code)
return name
end

function Base64ThemeEncoder:GetDefaultColor(id, colors)
if id == "outline" then return Template.colors[id] end

if id == "window_title_bar_corner_highlight" then
return colors["tab_corner_highlight"]
end

if id == "window_title_bar_highlight" then return colors["tab_highlight"] end

if id == "window_title_bar_background" then
return colors["tab_background"]
end

if id == "window_title_bar_shadow" then return colors["tab_shadow"] end
end

return Base64ThemeEncoder
6 changes: 6 additions & 0 deletions Theme Preferences/DefaultFont.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
return function()
return {
default = {name = "Aseprite", size = "9"},
mini = {name = "Aseprite Mini", size = "7"}
}
end
27 changes: 27 additions & 0 deletions Theme Preferences/DialogBounds.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
function GetWindowSize()
if app.apiVersion >= 25 then return app.window end

local dialog = Dialog()
dialog:show{wait = false}
dialog:close()

return Size(dialog.bounds.x * 2 + dialog.bounds.width,
dialog.bounds.y * 2 + dialog.bounds.height)
end

return function(size, position)
local window = GetWindowSize()

local uiScale = app.preferences.general["ui_scale"]
size = Size(size.width * uiScale, size.height * uiScale)

local x = (window.width - size.width) / 2
local y = (window.height - size.height) / 2

if position then
x = position.x
y = position.y
end

return Rectangle(x, y, size.width, size.height)
end
10 changes: 10 additions & 0 deletions Theme Preferences/ExportConfigurationDialog.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
return function(name, code, onClose)
local dialog = Dialog {title = "Export " .. name, onclose = onClose}

dialog --
:entry{label = "Code", text = code} --
:separator() --
:button{text = "Close"} --

return dialog
end
20 changes: 20 additions & 0 deletions Theme Preferences/FileProvider.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
local FileProvider = {}

function FileProvider:ReadAll(filePath)
local file = assert(io.open(filePath, "rb"))
local content = file:read("*all")
file:close()

return content
end

function FileProvider:Write(filePath, content)
local file = io.open(filePath, "w")

if file then
file:write(content)
file:close()
end
end

return FileProvider
222 changes: 222 additions & 0 deletions Theme Preferences/FontPreferences.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
local FontPreferencesDialog = dofile("./FontPreferencesDialog.lua")
local DefaultFont = dofile("./DefaultFont.lua")
local FileProvider = dofile("./FileProvider.lua")

local FontPreferences = {preferences = nil, availableFonts = {}}

function FontPreferences:Init(preferences)
self.preferences = preferences
self.preferences.font = self.preferences.font or DefaultFont()

self:_RefreshAvailableFonts()
end

function FontPreferences:GetCurrentFont() return self.preferences.font end

function FontPreferences:SetCurrentFont(font)
self.preferences.font = font or DefaultFont()
end

-- FUTURE: Revisit this, currently can cause issues and completely break the window layout rendering Aseprite unusable
function FontPreferences:VerifyScaling(font)
if font.default.type == "spritesheet" and font.mini.type == "spritesheet" then
return
end

local screenScale = app.preferences.general["screen_scale"]
local uiScale = app.preferences.general["ui_scale"]

if screenScale < uiScale then return end

app.preferences.general["screen_scale"] = uiScale
app.preferences.general["ui_scale"] = screenScale

app.alert {
title = "Warning",
text = "If the fonts appear blurry, please restart Aseprite for all changes to be applied."
}
end

function FontPreferences:_FindAll(content, patternStart, patternEnd)
local results = {}
local start = 0

while start ~= -1 do
local matchStart = string.find(content, patternStart, start)

if not matchStart then break end
local matchEnd = string.find(content, patternEnd,
matchStart + #patternStart)

local name = string.sub(content, matchStart + #patternStart,
matchEnd - #patternEnd)

table.insert(results, name)

start = matchEnd + #patternEnd
end

return results
end

function FontPreferences:_ParseFont(fontDescription)
local result = {}

local name = ""
local value = ""
local hasName = false

for i = 1, #fontDescription do
local char = string.sub(fontDescription, i, i)

if char == " " and not hasName then
-- If name and value are already found, save and reset
if #name > 0 and #value > 0 then
result[name] = value

name = ""
value = ""
hasName = false
end
elseif char == "=" or char == "/" then
-- Ignore
elseif char == "\"" then
if not hasName then
hasName = true
else
result[name] = value

name = ""
value = ""
hasName = false
end
elseif hasName then
value = value .. char
else
name = name .. char
end
end

return result
end

function FontPreferences:_ExtractFonts(filePath)
local fileContent = FileProvider:ReadAll(filePath)
fileContent = fileContent:gsub("[\n\r\t]+", " ")

local fontDeclarations = self:_FindAll(fileContent, "<font ", ">")

local result = {}

for _, fontDeclaration in ipairs(fontDeclarations) do
local font = self:_ParseFont(fontDeclaration)
table.insert(result, font)
end

return result
end

function FontPreferences:GetFontsFromDirectory(path, fonts)
-- Validate the path
if not app.fs.isDirectory(path) then return end

local files = app.fs.listFiles(path)
fonts = fonts or {}

for _, file in ipairs(files) do
local filePath = app.fs.joinPath(path, file)

if app.fs.isDirectory(filePath) then
self:GetFontsFromDirectory(filePath, fonts)
elseif file == "fonts.xml" or file == "theme.xml" then
local extractedFonts = self:_ExtractFonts(filePath)

for _, font in ipairs(extractedFonts) do
-- If the font has an ID it's a reference, not a declaration
if not font.id then fonts[font.name] = font end
end
elseif app.fs.fileExtension(filePath) == "ttf" then
local name = app.fs.fileTitle(filePath)

fonts[name] = {
name = name,
type = "truetype",
file = app.fs.fileName(filePath)
}
end
end

return fonts
end

function FontPreferences:_RefreshAvailableFonts()
self.availableFonts = {}

local systemFonts = self:_GetSystemFonts()
for name, font in pairs(systemFonts) do self.availableFonts[name] = font end

-- Aseprite Fonts
local asepriteDataDirectory = app.fs.filePath(app.fs.appPath)
local asepriteFonts = self:GetFontsFromDirectory(asepriteDataDirectory)
for name, font in pairs(asepriteFonts) do
self.availableFonts[name] = font
end

-- Declared Fonts
local extensionsDirectory = app.fs.joinPath(app.fs.userConfigPath,
"extensions")
local declaredFonts = self:GetFontsFromDirectory(extensionsDirectory)
for name, font in pairs(declaredFonts) do
self.availableFonts[name] = font
end
end

function FontPreferences:_GetSystemFonts()
-- Windows
local roamingPath = os.getenv("APPDATA")
local appDataPath = roamingPath and app.fs.filePath(roamingPath)
local windowsUserFontsPath = app.fs.joinPath(appDataPath,
"Local\\Microsoft\\Windows\\Fonts") or
""

-- Mac
local homePath = os.getenv("HOME")
local macUserFontsPath = app.fs.joinPath(homePath, "Library/Fonts") or ""

local fontsDirectories = {
"C:/Windows/Fonts", windowsUserFontsPath, -- Windows
"/Library/Fonts/", "/System/Library/Fonts/", macUserFontsPath, -- Mac
"~/.fonts", "/usr/local/share/fonts", "/usr/share/fonts" -- Linux
}

local systemFonts = {}

for _, fontsDirectory in ipairs(fontsDirectories) do
if app.fs.isDirectory(fontsDirectory) then
local fonts = self:GetFontsFromDirectory(fontsDirectory)

for fontName, font in pairs(fonts) do
systemFonts[fontName] = font
end
end
end

return systemFonts
end

function FontPreferences:OpenDialog(onClose, onSuccess)
local currentFont = FontPreferences:GetCurrentFont()

local onConfirm = function(newFont)
FontPreferences:SetCurrentFont(newFont)
onSuccess(newFont)
self:VerifyScaling(newFont)
end

local dialog = FontPreferencesDialog(currentFont, self.availableFonts,
onClose, onConfirm)

dialog:show{wait = false}
end

return FontPreferences
Loading