Skip to content

Commit 9c700c9

Browse files
committed
Add filter control abstractions for RmlUi Objects tab
Implements ComboBox, EditBox, and Label abstractions to make Object tab filters (Type, Terrain, Wreck, Search) work in RmlUi mode. Filter Control Abstractions (ui_controls.lua): - FilterLabel() - text labels for filter UI - FilterComboBox() - dropdown selectors for Type/Terrain/Wreck - FilterEditBox() - search text input - Mode-aware: creates RmlUi or Chili controls based on active mode RmlUi Filter Controls (rmlui_field_compat.lua): - RmlUiLabel - renders <span> with caption - RmlUiComboBox - renders <select> with options * Tracks selected index * OnSelect callback support * Select(itemIdx) method for programmatic changes - RmlUiEditBox - renders <input type="text"> * OnTextInput and OnKeyPress callback support * SetText() method for programmatic updates - All generate HTML via GenerateRml() method Editor Updates (editor.lua): - _FinalizeRmlUi() collects filter controls from children array - _FinalizeRmlUiNew() uses self.filterControls set by editor - Both methods generate filter panel HTML - Filters rendered between action buttons and grid/fields ObjectDefsView Updates (object_defs_view.lua): - UnitDefsView:MakeFilters() uses FilterLabel/FilterComboBox/FilterEditBox - FeatureDefsView:MakeFilters() uses new abstractions - Stores filters in self.filterControls for RmlUi rendering - Full backward compatibility with Chili mode View Event Binding (view.lua): - BindFieldEvents() now handles filterControls array - ComboBox: binds 'change' event, calls OnSelect with Chili signature - EditBox: binds 'input' and 'keyup' events for OnTextInput/OnKeyPress - Creates obj.text property for Chili API compatibility CSS Styles (springboard.rcss): - .filter-panel - flexbox layout with wrapping - .filter-label - styled text labels - .filter-combo - dropdown with hover/focus states - .filter-edit - text input with hover/focus states - Dark theme matching existing UI This enables full filtering functionality in Objects tab RmlUi mode: terrain type, unit type, wreck filters, and search.
1 parent 7b58b89 commit 9c700c9

File tree

6 files changed

+277
-28
lines changed

6 files changed

+277
-28
lines changed

scen_edit/view/editor.lua

Lines changed: 53 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -810,20 +810,35 @@ function Editor:_FinalizeRmlUi(children, opts)
810810
children = children or {}
811811
opts = opts or {}
812812

813-
-- Convert Chili buttons to RmlUi buttons
813+
-- Convert Chili buttons to RmlUi buttons, and collect RmlUi filter controls
814814
self.actionButtons = {}
815815
self.regularButtons = {}
816+
self.filterControls = self.filterControls or {} -- May already be set by editor
816817

817818
for _, child in ipairs(children) do
818819
if child and type(child) == "table" then
819-
local rmlButton = ConvertChiliButtonToRmlUi(child)
820-
if rmlButton then
821-
-- TabbedPanelButtons become action buttons
822-
if rmlButton.id and rmlButton.id:match("^action%-btn%-") then
823-
table.insert(self.actionButtons, rmlButton)
824-
-- Regular buttons
825-
elseif rmlButton.id and rmlButton.id:match("^btn%-") then
826-
table.insert(self.regularButtons, rmlButton)
820+
-- Check if this is already an RmlUi control (has GenerateRml method)
821+
if child.GenerateRml and type(child.GenerateRml) == "function" then
822+
-- It's an RmlUi control (filter control, etc.)
823+
if child.id and (child.id:match("^filter%-") or child.id:match("^action%-btn%-")) then
824+
if not Table.Contains(self.filterControls, child) then
825+
table.insert(self.filterControls, child)
826+
end
827+
if child.id:match("^action%-btn%-") then
828+
table.insert(self.actionButtons, child)
829+
end
830+
end
831+
else
832+
-- Try to convert Chili control to RmlUi
833+
local rmlButton = ConvertChiliButtonToRmlUi(child)
834+
if rmlButton then
835+
-- TabbedPanelButtons become action buttons
836+
if rmlButton.id and rmlButton.id:match("^action%-btn%-") then
837+
table.insert(self.actionButtons, rmlButton)
838+
-- Regular buttons
839+
elseif rmlButton.id and rmlButton.id:match("^btn%-") then
840+
table.insert(self.regularButtons, rmlButton)
841+
end
827842
end
828843
end
829844
end
@@ -839,6 +854,18 @@ function Editor:_FinalizeRmlUi(children, opts)
839854
buttonsHtml = buttonsHtml .. '</div>'
840855
end
841856

857+
-- Generate RML for filter controls
858+
local filtersHtml = ''
859+
if #self.filterControls > 0 then
860+
filtersHtml = '<div class="filter-panel">'
861+
for _, filter in ipairs(self.filterControls) do
862+
if filter.GenerateRml and not filter.id:match("^action%-btn%-") then
863+
filtersHtml = filtersHtml .. filter:GenerateRml()
864+
end
865+
end
866+
filtersHtml = filtersHtml .. '</div>'
867+
end
868+
842869
-- Generate RML for all fields
843870
local fieldsHtml = ''
844871
for _, fieldName in ipairs(self.fieldOrder) do
@@ -892,8 +919,8 @@ function Editor:_FinalizeRmlUi(children, opts)
892919
gridHtml = string.format('<div id="%s" class="grid-container"></div>', self.gridView.gridId)
893920
end
894921

895-
-- Combine buttons, grid, and fields
896-
self.generatedRml = buttonsHtml .. gridHtml .. fieldsHtml
922+
-- Combine buttons, filters, grid, and fields
923+
self.generatedRml = buttonsHtml .. filtersHtml .. gridHtml .. fieldsHtml
897924

898925
-- Mark as hidden by default
899926
self.hidden = true
@@ -903,6 +930,7 @@ end
903930
function Editor:_FinalizeRmlUiNew(layout, opts)
904931
self.actionButtons = layout.actionButtons or {}
905932
self.regularButtons = {}
933+
self.filterControls = self.filterControls or {} -- May already be set by editor
906934

907935
-- Generate RML for action buttons (placed at top)
908936
local buttonsHtml = ''
@@ -914,6 +942,18 @@ function Editor:_FinalizeRmlUiNew(layout, opts)
914942
buttonsHtml = buttonsHtml .. '</div>'
915943
end
916944

945+
-- Generate RML for filter controls
946+
local filtersHtml = ''
947+
if #self.filterControls > 0 then
948+
filtersHtml = '<div class="filter-panel">'
949+
for _, filter in ipairs(self.filterControls) do
950+
if filter.GenerateRml then
951+
filtersHtml = filtersHtml .. filter:GenerateRml()
952+
end
953+
end
954+
filtersHtml = filtersHtml .. '</div>'
955+
end
956+
917957
-- Generate RML for all fields
918958
local fieldsHtml = ''
919959
for _, fieldName in ipairs(self.fieldOrder) do
@@ -949,8 +989,8 @@ function Editor:_FinalizeRmlUiNew(layout, opts)
949989
gridHtml = string.format('<div id="%s" class="grid-container"></div>', self.gridView.gridId)
950990
end
951991

952-
-- Combine buttons, grid, and fields
953-
self.generatedRml = buttonsHtml .. gridHtml .. fieldsHtml
992+
-- Combine buttons, filters, grid, and fields
993+
self.generatedRml = buttonsHtml .. filtersHtml .. gridHtml .. fieldsHtml
954994

955995
-- Mark as hidden by default
956996
self.hidden = true

scen_edit/view/object/object_defs_view.lua

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -167,8 +167,9 @@ function ObjectDefsView:init()
167167
}
168168
)
169169

170-
-- Store grid reference for RmlUi rendering
170+
-- Store grid and filters reference for RmlUi rendering
171171
self.gridView = self.objectDefPanel
172+
self.filterControls = self.filters -- Store for event binding
172173

173174
self:Finalize(children)
174175
self:SetInvisibleFields(unpack(self.allFields))
@@ -261,12 +262,12 @@ function UnitDefsView:EnterState()
261262
end
262263
function UnitDefsView:MakeFilters()
263264
self.filters = {
264-
Label:New {
265+
FilterLabel {
265266
x = 1,
266267
y = 8 + SB.conf.C_HEIGHT * 5,
267268
caption = "Type:",
268269
},
269-
ComboBox:New {
270+
FilterComboBox {
270271
height = SB.conf.B_HEIGHT,
271272
x = 40,
272273
y = 1 + SB.conf.C_HEIGHT * 5,
@@ -282,12 +283,12 @@ function UnitDefsView:MakeFilters()
282283
end
283284
},
284285
},
285-
Label:New {
286+
FilterLabel {
286287
caption = "Terrain:",
287288
x = 140,
288289
y = 8 + SB.conf.C_HEIGHT * 5,
289290
},
290-
ComboBox:New {
291+
FilterComboBox {
291292
height = SB.conf.B_HEIGHT,
292293
x = 190,
293294
y = 1 + SB.conf.C_HEIGHT * 5,
@@ -303,12 +304,12 @@ function UnitDefsView:MakeFilters()
303304
end
304305
},
305306
},
306-
Label:New {
307+
FilterLabel {
307308
x = 1,
308309
y = 8 + SB.conf.C_HEIGHT * 7,
309310
caption = "Search:",
310311
},
311-
EditBox:New {
312+
FilterEditBox {
312313
height = SB.conf.B_HEIGHT,
313314
x = 60,
314315
y = 1 + SB.conf.C_HEIGHT * 7,
@@ -364,12 +365,12 @@ function FeatureDefsView:EnterState()
364365
end
365366
function FeatureDefsView:MakeFilters()
366367
self.filters = {
367-
Label:New {
368+
FilterLabel {
368369
x = 1,
369370
y = 8 + SB.conf.C_HEIGHT * 5,
370371
caption = "Type:",
371372
},
372-
ComboBox:New {
373+
FilterComboBox {
373374
height = SB.conf.B_HEIGHT,
374375
x = 40,
375376
y = 1 + SB.conf.C_HEIGHT * 5,
@@ -385,12 +386,12 @@ function FeatureDefsView:MakeFilters()
385386
end
386387
},
387388
},
388-
Label:New {
389+
FilterLabel {
389390
x = 140,
390391
y = 8 + SB.conf.C_HEIGHT * 5,
391392
caption = "Wreck:",
392393
},
393-
ComboBox:New {
394+
FilterComboBox {
394395
height = SB.conf.B_HEIGHT,
395396
x = 190,
396397
y = 1 + SB.conf.C_HEIGHT * 5,
@@ -406,12 +407,12 @@ function FeatureDefsView:MakeFilters()
406407
end
407408
},
408409
},
409-
Label:New {
410+
FilterLabel {
410411
caption = "Terrain:",
411412
x = 290,
412413
y = 8 + SB.conf.C_HEIGHT * 5,
413414
},
414-
ComboBox:New {
415+
FilterComboBox {
415416
y = 1 + SB.conf.C_HEIGHT * 5,
416417
height = SB.conf.B_HEIGHT,
417418
items = {
@@ -427,12 +428,12 @@ function FeatureDefsView:MakeFilters()
427428
end
428429
},
429430
},
430-
Label:New {
431+
FilterLabel {
431432
x = 1,
432433
y = 8 + SB.conf.C_HEIGHT * 7,
433434
caption = "Search:",
434435
},
435-
EditBox:New {
436+
FilterEditBox {
436437
height = SB.conf.B_HEIGHT,
437438
x = 60,
438439
y = 1 + SB.conf.C_HEIGHT * 7,

scen_edit/view/rcss/springboard.rcss

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,3 +374,61 @@ body#springboard {
374374
overflow: hidden;
375375
text-overflow: ellipsis;
376376
}
377+
378+
/* Filter Panel styles */
379+
.filter-panel {
380+
display: flex;
381+
flex-direction: row;
382+
flex-wrap: wrap;
383+
gap: 10dp;
384+
padding: 10dp;
385+
background-color: #2a2a2a;
386+
border-bottom: 1dp #555555;
387+
align-items: center;
388+
}
389+
390+
.filter-label {
391+
color: #cccccc;
392+
font-size: 12dp;
393+
margin-right: 5dp;
394+
}
395+
396+
.filter-combo {
397+
background-color: #3a3a3a;
398+
color: #ffffff;
399+
border: 1dp #555555;
400+
border-radius: 3dp;
401+
padding: 4dp 8dp;
402+
font-size: 12dp;
403+
min-width: 90dp;
404+
cursor: pointer;
405+
}
406+
407+
.filter-combo:hover {
408+
background-color: #4a4a4a;
409+
border-color: #777777;
410+
}
411+
412+
.filter-combo:focus {
413+
border-color: #3a7ebf;
414+
outline: none;
415+
}
416+
417+
.filter-edit {
418+
background-color: #3a3a3a;
419+
color: #ffffff;
420+
border: 1dp #555555;
421+
border-radius: 3dp;
422+
padding: 4dp 8dp;
423+
font-size: 12dp;
424+
min-width: 90dp;
425+
}
426+
427+
.filter-edit:hover {
428+
border-color: #777777;
429+
}
430+
431+
.filter-edit:focus {
432+
border-color: #3a7ebf;
433+
outline: none;
434+
}

scen_edit/view/rmlui_field_compat.lua

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,4 +134,84 @@ function RmlUiTabbedPanelButton:GenerateRml()
134134
return html
135135
end
136136

137+
-- RmlUi Label - for filter UI labels
138+
RmlUiLabel = LCS.class{}
139+
140+
function RmlUiLabel:init(opts)
141+
_BUTTON_INDEX = _BUTTON_INDEX + 1
142+
self.id = "filter-label-" .. tostring(_BUTTON_INDEX)
143+
self.caption = opts.caption or ""
144+
self.x = opts.x
145+
self.y = opts.y
146+
end
147+
148+
function RmlUiLabel:GenerateRml()
149+
return string.format('<span id="%s" class="filter-label">%s</span>', self.id, self.caption)
150+
end
151+
152+
-- RmlUi ComboBox - for filter dropdowns
153+
RmlUiComboBox = LCS.class{}
154+
155+
function RmlUiComboBox:init(opts)
156+
_BUTTON_INDEX = _BUTTON_INDEX + 1
157+
self.id = "filter-combo-" .. tostring(_BUTTON_INDEX)
158+
self.items = opts.items or {}
159+
self.OnSelect = opts.OnSelect or {}
160+
self.selected = 1
161+
self.width = opts.width
162+
self.x = opts.x
163+
self.y = opts.y
164+
end
165+
166+
function RmlUiComboBox:GenerateRml()
167+
local html = string.format('<select id="%s" class="filter-combo">', self.id)
168+
for i, item in ipairs(self.items) do
169+
local selected = (i == self.selected) and ' selected=""' or ''
170+
html = html .. string.format('<option value="%d"%s>%s</option>', i, selected, item)
171+
end
172+
html = html .. '</select>'
173+
return html
174+
end
175+
176+
function RmlUiComboBox:Select(itemIdx)
177+
self.selected = itemIdx
178+
-- Update DOM if element exists
179+
if SB.view and SB.view.mainDocument then
180+
local element = SB.view.mainDocument:GetElementById(self.id)
181+
if element then
182+
element.value = tostring(itemIdx)
183+
end
184+
end
185+
end
186+
187+
-- RmlUi EditBox - for search text input
188+
RmlUiEditBox = LCS.class{}
189+
190+
function RmlUiEditBox:init(opts)
191+
_BUTTON_INDEX = _BUTTON_INDEX + 1
192+
self.id = "filter-edit-" .. tostring(_BUTTON_INDEX)
193+
self.text = opts.text or ""
194+
self.OnTextInput = opts.OnTextInput or {}
195+
self.OnKeyPress = opts.OnKeyPress or {}
196+
self.width = opts.width
197+
self.x = opts.x
198+
self.y = opts.y
199+
end
200+
201+
function RmlUiEditBox:GenerateRml()
202+
return string.format('<input type="text" id="%s" class="filter-edit" value="%s" placeholder="Search..."/>',
203+
self.id, self.text)
204+
end
205+
206+
function RmlUiEditBox:SetText(text)
207+
self.text = text
208+
-- Update DOM if element exists
209+
if SB.view and SB.view.mainDocument then
210+
local element = SB.view.mainDocument:GetElementById(self.id)
211+
if element then
212+
element.value = text
213+
end
214+
end
215+
end
216+
137217
Log.Notice("RmlUi field compatibility layer loaded - original API maintained")

0 commit comments

Comments
 (0)