Skip to content

Commit 71d23ee

Browse files
committed
- Updated theme plugin to support changing themes on runtime
- Added 4 themes - Added Cache System for States
1 parent e4ee937 commit 71d23ee

11 files changed

Lines changed: 304 additions & 46 deletions

File tree

src/elements/BaseElement.lua

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ function BaseElement:init(props, basalt)
101101
self.basalt = basalt
102102
self._registeredEvents = {}
103103
self._registeredStates = {}
104+
self._cachedActiveStates = nil
104105

105106
local currentClass = getmetatable(self).__index
106107

@@ -142,6 +143,7 @@ function BaseElement:postInit()
142143
return self
143144
end
144145
self._postInitialized = true
146+
self._modifiedProperties = {}
145147
if(self._props)then
146148
for k,v in pairs(self._props)do
147149
self.set(k, v)
@@ -234,6 +236,7 @@ function BaseElement:setState(stateName, priority)
234236
states[stateName] = priority or 0
235237

236238
self.set("states", states)
239+
self._cachedActiveStates = nil
237240
return self
238241
end
239242

@@ -246,6 +249,7 @@ function BaseElement:unsetState(stateName)
246249
if states[stateName] ~= nil then
247250
states[stateName] = nil
248251
self.set("states", states)
252+
self._cachedActiveStates = nil
249253
end
250254
return self
251255
end
@@ -282,6 +286,11 @@ end
282286
--- @shortDescription Gets all active states
283287
--- @return table states Array of {name, priority} sorted by priority
284288
function BaseElement:getActiveStates()
289+
-- Return cached version if available
290+
if self._cachedActiveStates then
291+
return self._cachedActiveStates
292+
end
293+
285294
local states = self.get("states")
286295
local result = {}
287296

@@ -291,6 +300,7 @@ function BaseElement:getActiveStates()
291300

292301
table.sort(result, function(a, b) return a.priority > b.priority end)
293302

303+
self._cachedActiveStates = result
294304
return result
295305
end
296306

src/elements/Frame.lua

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ function Frame.new()
2929
self.class = Frame
3030
self.set("width", 12)
3131
self.set("height", 6)
32-
self.set("background", colors.gray)
3332
self.set("z", 10)
3433
return self
3534
end

src/elements/Label.lua

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ function Label.new()
3737
local self = setmetatable({}, Label):__init()
3838
self.class = Label
3939
self.set("z", 3)
40-
self.set("foreground", colors.black)
4140
self.set("backgroundEnabled", false)
4241
return self
4342
end
@@ -49,10 +48,6 @@ end
4948
--- @protected
5049
function Label:init(props, basalt)
5150
VisualElement.init(self, props, basalt)
52-
if(self.parent)then
53-
self.set("background", self.parent.get("background"))
54-
self.set("foreground", self.parent.get("foreground"))
55-
end
5651
self.set("type", "Label")
5752
return self
5853
end

src/elements/List.lua

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,6 @@ function List.new()
7171
self.set("width", 16)
7272
self.set("height", 8)
7373
self.set("z", 5)
74-
self.set("background", colors.gray)
7574
return self
7675
end
7776

src/layoutManager.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,4 +114,4 @@ function LayoutManager.destroy(instance)
114114
end
115115
end
116116

117-
return LayoutManager
117+
return LayoutManager

src/plugins/theme.lua

Lines changed: 102 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,49 @@ local errorManager = require("errorManager")
44

55
local defaultTheme = {
66
default = {
7-
background = colors.lightGray,
7+
background = colors.cyan,
88
foreground = colors.black,
99
},
1010
BaseFrame = {
1111
background = colors.white,
1212
foreground = colors.black,
1313

14-
Frame = {
14+
Container = {
15+
default = {
16+
background = colors.cyan,
17+
foreground = colors.black,
18+
},
1519
background = colors.black,
16-
names = {
17-
basaltDebugLogClose = {
18-
background = colors.blue,
19-
foreground = colors.white
20+
Button = {
21+
background = colors.cyan,
22+
foreground = colors.black,
23+
states = {
24+
clicked = {
25+
background = colors.white,
26+
foreground = colors.black,
27+
}
2028
}
2129
},
30+
Input = {
31+
background = colors.cyan,
32+
foreground = colors.black,
33+
},
34+
Label = {
35+
foreground = colors.white,
36+
},
2237
},
2338
Button = {
2439
background = colors.cyan,
2540
foreground = colors.black,
41+
states = {
42+
clicked = {
43+
background = colors.black,
44+
foreground = colors.cyan,
45+
}
46+
}
47+
},
48+
Label = {
49+
foreground = colors.black,
2650
},
2751

2852
names = {
@@ -96,26 +120,6 @@ local function lookUpTemplate(theme, path)
96120
return current
97121
end
98122

99-
local function getDefaultProperties(theme, elementType)
100-
local result = {}
101-
if theme.default then
102-
for k,v in pairs(theme.default) do
103-
if type(v) ~= "table" then
104-
result[k] = v
105-
end
106-
end
107-
108-
if theme.default[elementType] then
109-
for k,v in pairs(theme.default[elementType]) do
110-
if type(v) ~= "table" then
111-
result[k] = v
112-
end
113-
end
114-
end
115-
end
116-
return result
117-
end
118-
119123
local function applyNamedStyles(result, theme, elementType, elementName, themeTable)
120124
if theme.default and theme.default.names and theme.default.names[elementName] then
121125
for k,v in pairs(theme.default.names[elementName]) do
@@ -139,17 +143,46 @@ end
139143

140144
local function collectThemeProps(theme, path, elementType, elementName)
141145
local result = {}
142-
local themeTable = lookUpTemplate(theme, path)
143-
if themeTable then
144-
for k,v in pairs(themeTable) do
146+
if theme.default then
147+
for k,v in pairs(theme.default) do
145148
if type(v) ~= "table" then
146149
result[k] = v
147150
end
148151
end
149152
end
153+
local current = theme
154+
for i = 1, #path do
155+
local types = path[i]
156+
local found = false
157+
158+
for _, elementType in ipairs(types) do
159+
if current[elementType] then
160+
current = current[elementType]
161+
found = true
162+
if current.default then
163+
for k,v in pairs(current.default) do
164+
if type(v) ~= "table" then
165+
result[k] = v
166+
end
167+
end
168+
end
169+
break
170+
end
171+
end
172+
173+
if not found then
174+
current = nil
175+
break
176+
end
177+
end
150178

151-
if next(result) == nil then
152-
result = getDefaultProperties(theme, elementType)
179+
local themeTable = lookUpTemplate(theme, path)
180+
if themeTable then
181+
for k,v in pairs(themeTable) do
182+
if type(v) ~= "table" or k == "states" then
183+
result[k] = v
184+
end
185+
end
153186
end
154187

155188
applyNamedStyles(result, theme, elementType, elementName, themeTable)
@@ -163,22 +196,53 @@ end
163196
--- @param applyToChildren boolean? Whether to apply theme to child elements (default: true)
164197
--- @return BaseElement self The element instance
165198
function BaseElement:applyTheme(applyToChildren)
199+
local backup = {}
200+
if self._modifiedProperties then
201+
for prop, _ in pairs(self._modifiedProperties) do
202+
backup[prop] = true
203+
end
204+
end
205+
166206
local styles = self:getTheme()
167207
if(styles ~= nil) then
168208
for prop, value in pairs(styles) do
169-
local config = self._properties[prop]
170-
if(config)then
171-
if((config.type)=="color")then
172-
if(type(value)=="string")then
173-
if(colors[value])then
174-
value = colors[value]
209+
if prop ~= "states" and not backup[prop] then
210+
local config = self._properties[prop]
211+
if(config)then
212+
if((config.type)=="color")then
213+
if(type(value)=="string")then
214+
if(colors[value])then
215+
value = colors[value]
216+
end
217+
end
218+
end
219+
self.set(prop, value)
220+
end
221+
end
222+
end
223+
if styles.states then
224+
for stateName, stateConfig in pairs(styles.states) do
225+
for prop, value in pairs(stateConfig) do
226+
if prop ~= "priority" then
227+
local config = self._properties[prop]
228+
local capitalizedName = prop:sub(1,1):upper() .. prop:sub(2)
229+
if(config)then
230+
if((config.type)=="color")then
231+
if(type(value)=="string")then
232+
if(colors[value])then
233+
value = colors[value]
234+
end
235+
end
236+
end
237+
self["set" .. capitalizedName .. "State"](self, stateName, value)
175238
end
176239
end
177240
end
178-
self.set(prop, value)
179241
end
180242
end
181243
end
244+
self._modifiedProperties = backup
245+
182246
if(applyToChildren~=false)then
183247
if(self:isType("Container"))then
184248
local children = self.get("children")

src/propertySystem.lua

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,7 @@ function PropertySystem:__init()
263263
self._values = {}
264264
self._observers = {}
265265
self._states = {}
266+
self._modifiedProperties = {}
266267

267268
self.set = function(name, value, ...)
268269
local oldValue = self._values[name]
@@ -275,6 +276,7 @@ function PropertySystem:__init()
275276
self:updateRender()
276277
end
277278
self._values[name] = applyHooks(self, name, value, config)
279+
self._modifiedProperties[name] = true
278280
if oldValue ~= value and self._observers[name] then
279281
for _, callback in ipairs(self._observers[name]) do
280282
callback(self, value, oldValue)
@@ -431,6 +433,7 @@ function PropertySystem:_updateProperty(name, value)
431433
oldValue = oldValue(self)
432434
end
433435

436+
self._modifiedProperties[name] = true
434437
self._values[name] = value
435438
local newValue = type(value) == "function" and value(self) or value
436439

themes/classic.json

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
{
2+
"theme": "classic",
3+
"default": {
4+
"background": "black",
5+
"foreground": "lightGray"
6+
},
7+
"BaseFrame": {
8+
"background": "lightGray",
9+
"Container": {
10+
"background": "gray",
11+
"foreground": "white",
12+
"Button" : {
13+
"background" : "black",
14+
"foreground" : "lightGray",
15+
"states": {
16+
"clicked": {
17+
"background": "white",
18+
"foreground": "black"
19+
}
20+
}
21+
},
22+
"Input": {
23+
"background": "black",
24+
"foreground": "lightGray"
25+
}
26+
},
27+
"Button": {
28+
"background": "black",
29+
"foreground": "lightGray",
30+
"states": {
31+
"clicked": {
32+
"background": "white",
33+
"foreground": "black"
34+
}
35+
}
36+
},
37+
"Label": {
38+
"foreground": "black"
39+
},
40+
"names": {
41+
"basaltDebugLog": {
42+
"background": "black",
43+
"foreground": "white"
44+
}
45+
}
46+
}
47+
}

0 commit comments

Comments
 (0)