diff options
author | 2021-10-31 12:31:16 +1100 | |
---|---|---|
committer | 2021-10-31 12:31:16 +1100 | |
commit | d64ea5331b2312f81df464fb22dcef0191216d86 (patch) | |
tree | a3f3784371da401e6a675e5b6b9734b88281a08d /plugins/commonui/init.lua | |
parent | cfffc54b61cabc5ef9533396bf87324eb5eeb63e (diff) |
-frontend: Refactored menu event handling and fixed a number of issues. (#8777)
* Moved common code for drawing about box, info viewer, and other text box menus to a base class; removed the last of the info viewer logic and the multi-line item hack from the base menu class.
* Added previous/next group navigation for general inputs and plugin input selection menus.
* Moved message catalog logic to lib/util, allowing osd and emu to use localised messages.
* Made the base menu class use the UI manager’s feature for holding session state rather than a static map and mutex.
* Improved menu event handling model, and fixed many issues, particularly with menus behaving badly when hidden/shown.
* Added better support for menus that don’t participate in the usual menu stack, like the menuless sliders and the save/load state menus.
* Made a number of menus refresh state when being shown after being hidden (fixes MT08121 among other issues).
* Fixed indication of mounted slot option in the slot option details menu.
* Improved appearance of background menus when emulation isn't running - draw all menus in the stack, and darken the background menus to make the edges of the active menu clearer.
* Fixed locale issues in -listxml.
-debugger: Made GUI debuggers more uniform.
* Added new memory view features to Win32 debugger.
* Fixed spelling of hexadecimal in Cocoa debugger and added decimal address option.
* Fixed duplicate keyboard shortcut in Cocoa debugger (Shift-Cmd-D was both new device window and 64-bit float format).
* Made keyboard shortcuts slightly more consistent across debuggers.
-plugins: Moved input selection menu and sequence polling code to a common library. Fixed the issue that prevented keyboard inputs being mapped with -steadykey on.
-docs: Started adding some documentation for MAME's internal UI, and updated the list of example front-ends.
-Regenerated message catalog sources. For translators, the new strings are mostly:
* The names of the inputs provided by the OS-dependent layer for things like fullscreen and video features. These show up in the user interface inputs menu.
* The names for automatically generated views. These show up in the video options menu - test with a system with a lot of screens to see more variants.
* The input macro plugin UI.
* A few format strings for analog input assignments.
* A few strings for the about box header.
Diffstat (limited to 'plugins/commonui/init.lua')
-rw-r--r-- | plugins/commonui/init.lua | 214 |
1 files changed, 214 insertions, 0 deletions
diff --git a/plugins/commonui/init.lua b/plugins/commonui/init.lua new file mode 100644 index 00000000000..26b65a5e1b5 --- /dev/null +++ b/plugins/commonui/init.lua @@ -0,0 +1,214 @@ +-- license:BSD-3-Clause +-- copyright-holders:Vas Crabb +local exports = { + name = 'commonui', + version = '0.0.1', + description = 'Common plugin UI helpers', + license = 'BSD-3-Clause', + author = { name = 'Vas Crabb' } } + + +local commonui = exports + + +function commonui.input_selection_menu(action, title, filter) + menu = { } + + local choices + local index_first_choice + local index_cancel + + local function populate_choices() + local ioport = manager.machine.ioport + + local function compare(a, b) + if a.device.tag < b.device.tag then + return true + elseif a.device.tag > b.device.tag then + return false + end + groupa = ioport:type_group(a.type, a.player) + groupb = ioport:type_group(b.type, b.player) + if groupa < groupb then + return true + elseif groupa > groupb then + return false + elseif a.type < b.type then + return true + elseif a.type > b.type then + return false + else + return a.name < b.name + end + end + + choices = { } + for tag, port in pairs(manager.machine.ioport.ports) do + for name, field in pairs(port.fields) do + if (not filter) or filter(field) then + table.insert(choices, field) + end + end + end + table.sort(choices, compare) + + local index = 1 + local prev + while index <= #choices do + local current = choices[index] + if (not prev) or (prev.device.tag ~= current.device.tag) then + table.insert(choices, index, false) + index = index + 2 + else + index = index + 1 + end + prev = current + end + end + + function menu:populate(initial_selection) + if not choices then + populate_choices() + end + + local items = { } + + if title then + table.insert(items, { title, '', 'off' }) + table.insert(items, { '---', '', '' }) + end + + index_first_choice = #items + 1 + local selection = index_first_choice + for index, field in ipairs(choices) do + if field then + table.insert(items, { _p('input-name', field.name), '', '' }) + if initial_selection and (field.port.tag == initial_selection.port.tag) and (field.mask == initial_selection.mask) and (field.type == initial_selection.type) then + selection = #items + initial_selection = nil + end + else + local device = choices[index + 1].device + if device.owner then + table.insert(items, { string.format(_p('plugin-commonui', '%s [root%s]'), device.name, device.tag), '', 'heading' }) + else + table.insert(items, { string.format(_p('plugin-commonui', '[root%s]'), device.tag), '', 'heading' }) + end + end + end + + table.insert(items, { '---', '', '' }) + table.insert(items, { _p('plugin-commonui', 'Cancel'), '', '' }) + index_cancel = #items + + return items, selection + end + + function menu:handle(index, event) + local selection + if (event == 'cancel') or ((index == input_item_cancel) and (event == 'select')) then + action(nil) + return true + elseif event == 'select' then + local field = choices[index - index_first_choice + 1] + if field then + action(field) + return true + end + elseif event == 'prevgroup' then + local found_break = false + while (index > index_first_choice) and (not selection) do + index = index - 1 + if not choices[index - index_first_choice + 1] then + if found_break then + selection = index + 1 + else + found_break = true + end + end + end + elseif event == 'nextgroup' then + while ((index - index_first_choice + 2) < #choices) and (not selection) do + index = index + 1 + if not choices[index - index_first_choice + 1] then + selection = index + 1 + end + end + end + return false, selection + end + + return menu +end + + +function commonui.switch_polling_helper(starting_sequence) + helper = { } + + local machine = manager.machine + local cancel = machine.ioport:token_to_input_type('UI_CANCEL') + local cancel_prompt = manager.ui:get_general_input_setting(cancel) + local input = machine.input + local uiinput = machine.uiinput + local poller = input:switch_sequence_poller() + local modified_ticks = 0 + + if starting_sequence then + poller:start(starting_sequence) + else + poller:start() + end + + function helper:overlay(items, selection, flags) + if flags then + flags = flags .. " nokeys" + else + flags = "nokeys" + end + return items, selection, flags + end + + function helper:poll() + -- prevent race condition between uiinput:pressed() and poll() + if (modified_ticks == 0) and poller.modified then + modified_ticks = emu.osd_ticks() + end + + if uiinput:pressed(cancel) then + -- UI_CANCEL pressed, abort + machine:popmessage() + if (not poller.modified) or (modified_ticks == emu.osd_ticks()) then + -- cancelled immediately + self.sequence = nil + return true -- TODO: communicate this better? + else + -- entered something before cancelling + self.sequence = nil + return true + end + elseif poller:poll() then + if poller.valid then + -- valid sequence entered + machine:popmessage() + self.sequence = poller.sequence + return true + else + -- invalid sequence entered + machine:popmessage(_p('plugin-commonui', 'Invalid sequence entered')) + self.sequence = nil + return true + end + else + machine:popmessage(string.format( + _p('plugin-commonui', 'Enter sequence or press %s to cancel\n%s'), + cancel_prompt, + input:seq_name(poller.sequence))) + return false + end + end + + return helper +end + + +return exports |