|
|
|
|
|
|
|
|
|
|
|
DefineClass.XAction = { |
|
__parents = { "XRollover" }, |
|
properties = { |
|
{ category = "Action", id = "ActionId", editor = "text", default = "" }, |
|
{ category = "Action", id = "ActionMode", editor = "text", default = "" }, |
|
{ category = "Action", id = "InheritedActionModes", editor = "text", default = "", read_only = true, help = "ActionModes inherited from parent if ActionMode is empty", dont_save = true }, |
|
{ category = "Action", id = "ActionSortKey", editor = "text", default = "", |
|
buttons = { { name = "Rebuild", func = "RebuildSortKeys" } }, |
|
}, |
|
{ category = "Action", id = "ActionTranslate", editor = "bool", default = true, }, |
|
{ category = "Action", id = "ActionName", editor = "text", default = "", translate = function(obj) return obj:GetProperty("ActionTranslate") end, }, |
|
{ category = "Action", id = "ActionDescription", editor = "text", default = "", translate = function(obj) return obj:GetProperty("ActionTranslate") end, }, |
|
{ category = "Action", id = "ActionIcon", editor = "ui_image", default = "", }, |
|
{ category = "Action", id = "ActionMenubar", editor = "text", default = "", }, |
|
{ category = "Action", id = "ActionToolbar", editor = "text", default = "" }, |
|
{ category = "Action", id = "ActionToolbarSplit", editor = "bool", default = false }, |
|
{ category = "Action", id = "ActionToolbarSection", editor = "text", default = "" }, |
|
{ category = "Action", id = "ActionUIStyle", editor = "choice", default = "auto", items = {"auto", "gamepad", "keyboard"}, }, |
|
{ category = "Action", id = "ActionShortcut", editor = "shortcut", default = "" }, |
|
{ category = "Action", id = "ActionShortcut2", editor = "shortcut", default = "" }, |
|
{ category = "Action", id = "ActionGamepad", editor = "shortcut", shortcut_type = "gamepad", default = "" }, |
|
{ category = "Action", id = "ActionGamepadHold", editor = "bool", default = false }, |
|
{ category = "Action", id = "ActionBindable", editor = "bool", default = false }, |
|
{ category = "Action", id = "ActionMouseBindable", editor = "bool", default = true }, |
|
{ category = "Action", id = "ActionBindSingleKey", editor = "bool", default = false }, |
|
{ category = "Action", id = "BindingsMenuCategory", editor = "text", default = "Default" }, |
|
{ category = "Action", id = "ActionButtonTemplate", editor = "choice", default = false, items = function() return XTemplateCombo("XButton") end, }, |
|
{ category = "Action", id = "ActionToggle", editor = "bool", default = false }, |
|
{ category = "Action", id = "ActionToggled", editor = "func", params = "self, host", read_only = function(self) return not self:GetProperty("ActionToggle") end, }, |
|
{ category = "Action", id = "ActionToggledIcon", editor = "ui_image", default = "", read_only = function(self) return not self:GetProperty("ActionToggle") end, }, |
|
{ category = "Action", id = "ActionState", editor = "func", params = "self, host" }, |
|
{ category = "Action", id = "OnActionEffect", editor = "choice", default = "", items = {"", "popup", "back", "close", "mode"}, }, |
|
{ category = "Action", id = "OnActionParam", editor = "text", default = "" }, |
|
{ category = "Action", id = "OnAction", editor = "func", params = "self, host, source, ...", }, |
|
{ category = "Action", id = "OnShortcutUp", editor = "func", params = "self, host, source, ...", default = false }, |
|
{ category = "Action", id = "OnAltAction", editor = "func", params = "self, host, source, ...", default = false}, |
|
{ category = "Action", id = "IgnoreRepeated", editor = "bool", default = false }, |
|
{ category = "Action", id = "ActionContexts", editor = "string_list", default = false }, |
|
|
|
{ category = "FX", id = "FXMouseIn", editor = "text", default = "", }, |
|
{ category = "FX", id = "FXPress", editor = "text", default = "", }, |
|
{ category = "FX", id = "FXPressDisabled", editor = "text", default = "", }, |
|
|
|
|
|
{ category = "Rollover", id = "RolloverTranslate", editor = false }, |
|
{ category = "Rollover", id = "RolloverAnchor", editor = false }, |
|
{ category = "Rollover", id = "RolloverText", editor = "text", default = "", translate = function(obj) return obj:GetProperty("ActionTranslate") end, lines = 3, }, |
|
{ category = "Rollover", id = "RolloverDisabledText", editor = "text", default = "", translate = function(obj) return obj:GetProperty("ActionTranslate") end, lines = 3, }, |
|
}, |
|
|
|
|
|
default_ActionShortcut = false, |
|
default_ActionShortcut2 = false, |
|
default_ActionGamepad = false, |
|
|
|
shortcut_up_thread = false, |
|
host = false, |
|
|
|
multi_mode_cache = false |
|
} |
|
|
|
function XAction:RegisterInHost(host, replace_matching_id) |
|
self.host = host |
|
if host then host:_InternalAddAction(self, replace_matching_id) end |
|
self:BindShortcuts() |
|
|
|
if self.OnShortcutUp and host and self.OnAction ~= XAction.OnAction then |
|
local oldAction = self.OnAction |
|
self.OnAction = function(self, ...) |
|
oldAction(self, ...) |
|
|
|
local keyOne = self.ActionShortcut and VKStrNamesInverse[self.ActionShortcut] |
|
local keyTwo = self.ActionShortcut2 and VKStrNamesInverse[self.ActionShortcut2] |
|
local downKey = (keyOne and terminal.IsKeyPressed(keyOne) and keyOne) or (keyTwo and terminal.IsKeyPressed(keyTwo) and keyTwo) |
|
|
|
if IsValidThread(self.shortcut_up_thread) then |
|
DeleteThread(self.shortcut_up_thread) |
|
end |
|
self.shortcut_up_thread = CreateRealTimeThread(function(self, ...) |
|
while downKey and terminal.IsKeyPressed(downKey) and not terminal.desktop.inactive do |
|
Sleep(16) |
|
end |
|
self.OnShortcutUp(self, ...) |
|
end, self, ...) |
|
end |
|
end |
|
end |
|
|
|
function XAction:Init(parent, context, replace_matching_id) |
|
self:RegisterInHost(GetActionsHost(parent), replace_matching_id) |
|
end |
|
|
|
function XAction:BindShortcuts() |
|
self.default_ActionShortcut = self.ActionShortcut |
|
self.default_ActionShortcut2 = self.ActionShortcut2 |
|
self.default_ActionGamepad = self.ActionGamepad |
|
if self.ActionBindable then |
|
local bindings = AccountStorage and AccountStorage.Shortcuts[self.ActionId] |
|
if bindings then |
|
self:SetActionShortcuts(bindings[1] or self.ActionShortcut, bindings[2] or self.ActionShortcut2, bindings[3] or self.ActionGamepad) |
|
end |
|
end |
|
end |
|
|
|
local function RemoveShortcut(action, name, shortcut) |
|
shortcut = shortcut or "" |
|
local old_shortcut = action[name] |
|
if shortcut == old_shortcut then |
|
|
|
return |
|
end |
|
|
|
action[name] = nil |
|
local host = action.host |
|
if not host then return end |
|
|
|
|
|
host:CallHostParents("RemoveShortcutToAction", action, old_shortcut) |
|
end |
|
|
|
local function AddShortcut(action, name, shortcut) |
|
shortcut = shortcut or "" |
|
local old_shortcut = action[name] |
|
if shortcut == old_shortcut then |
|
|
|
return |
|
end |
|
|
|
action[name] = shortcut |
|
local host = action.host |
|
if not host then return end |
|
|
|
|
|
host:CallHostParents("AddShortcutToAction", action, shortcut) |
|
end |
|
|
|
function XAction:SetActionShortcuts(shortcut, shortcut2, shortcut_gamepad) |
|
|
|
RemoveShortcut(self, "ActionShortcut", shortcut) |
|
RemoveShortcut(self, "ActionShortcut2", shortcut2) |
|
RemoveShortcut(self, "ActionGamepad", shortcut_gamepad) |
|
|
|
AddShortcut(self, "ActionShortcut", shortcut) |
|
AddShortcut(self, "ActionShortcut2", shortcut2) |
|
AddShortcut(self, "ActionGamepad", shortcut_gamepad) |
|
end |
|
|
|
function XAction:SetActionMenubar(menubar) |
|
local host = self.host |
|
if host and self.ActionMenubar ~= menubar then |
|
host:CallHostParents("RemoveMenubarAction", self) |
|
end |
|
self.ActionMenubar = menubar |
|
if not host then return end |
|
host:CallHostParents("AddMenubarAction", self) |
|
end |
|
|
|
function XAction:SetActionToolbar(toolbar) |
|
local host = self.host |
|
if host and self.ActionToolbar ~= toolbar then |
|
host:CallHostParents("RemoveToolbarAction", self) |
|
end |
|
self.ActionToolbar = toolbar |
|
if not host then return end |
|
host:CallHostParents("AddToolbarAction", self) |
|
end |
|
|
|
function XAction:SetActionSortKey(sort_key) |
|
self.ActionSortKey = sort_key |
|
if not self.host then return end |
|
self.host:InvalidateActionSortKey(self) |
|
end |
|
|
|
function XAction:ActionState(host) |
|
end |
|
|
|
function XAction:ActionToggled(host) |
|
end |
|
|
|
function XAction:OnAction(host, source, ...) |
|
local effect = self.OnActionEffect |
|
local param = self.OnActionParam |
|
if effect == "close" and host and host.window_state ~= "destroying" then |
|
host:Close(param ~= "" and param or nil, source, ...) |
|
elseif effect == "mode" and host then |
|
assert(IsKindOf(host, "XDialog")) |
|
host:SetMode(param) |
|
elseif effect == "back" and host then |
|
assert(IsKindOf(host, "XDialog")) |
|
SetBackDialogMode(host) |
|
elseif effect == "popup" then |
|
local actions_view = GetParentOfKind(source, "XActionsView") |
|
if actions_view then |
|
actions_view:PopupAction(self.ActionId, host, source) |
|
else |
|
XShortcutsTarget:OpenPopupMenu(self.ActionId, terminal.GetMousePos()) |
|
end |
|
else |
|
|
|
end |
|
end |
|
|
|
function XAction:OnXTemplateSetProperty(prop_id, old_value) |
|
|
|
if prop_id == "ActionTranslate" then |
|
self:UpdateLocalizedProperty("ActionName", self.ActionTranslate) |
|
self:UpdateLocalizedProperty("RolloverText", self.ActionTranslate) |
|
self:UpdateLocalizedProperty("RolloverDisabledText", self.ActionTranslate) |
|
ObjModified(self) |
|
end |
|
if prop_id == "ActionSortKey" and self.ActionSortKey ~= "" then |
|
local preset = GetParentTableOfKind(self, "XTemplate") |
|
preset.RequireActionSortKeys = true |
|
end |
|
end |
|
|
|
function XAction:EnabledInMode(mode) |
|
local myMode = self.ActionMode |
|
if myMode == "" then return true end |
|
if mode == myMode then return true end |
|
|
|
if not self.multi_mode_cache or self.multi_mode_cache.strsrc ~= myMode then |
|
local modeCache = { strsrc = myMode } |
|
for str in string.gmatch(myMode, "([%w%-_]+)") do |
|
modeCache[str] = true |
|
end |
|
self.multi_mode_cache = modeCache |
|
end |
|
return self.multi_mode_cache[mode] |
|
end |
|
|
|
local function assign_sortkeys(node, sortkey) |
|
if node:IsKindOf("XTemplateAction") and node.ActionId ~= "" then |
|
if node.ActionSortKey ~= "" then |
|
print("Overwriting SortKey of", node.ActionId, "to", node.ActionSortKey) |
|
end |
|
node:SetActionSortKey(tostring(sortkey * 10)) |
|
sortkey = sortkey + 1 |
|
end |
|
for _, item in ipairs(node) do |
|
sortkey = assign_sortkeys(item, sortkey) |
|
end |
|
return sortkey |
|
end |
|
|
|
function XAction:RebuildSortKeys(root, prop_id, ged, btn_param) |
|
if ged:WaitQuestion("Rebuild SortKeys", "This will assign SortKeys to each Action in the current file, in the order\nthey appear, overwriting existing ones.\n\nContinue?", "OK", "Cancel") ~= "ok" then |
|
return |
|
end |
|
assign_sortkeys(root, 100) |
|
root.RequireActionSortKeys = true |
|
ObjModified(self) |
|
ObjModified(root) |
|
end |
|
|
|
|
|
|
|
DefineClass.XActionsHost = { |
|
__parents = { "XContextWindow", "XHoldButton" }, |
|
properties = { |
|
{ category = "Actions", id = "ActionsMode", editor = "text", default = "", }, |
|
{ category = "Actions", id = "Translate", editor = "bool", default = false, }, |
|
{ category = "Actions", id = "HostInParent", editor = "bool", default = false, }, |
|
}, |
|
actions = false, |
|
shortcut_to_actions = false, |
|
menubar_actions = false, |
|
toolbar_actions = false, |
|
action_hold_buttons = false, |
|
|
|
dirty_actions_order = false, |
|
dirty_menubars = false, |
|
dirty_toolbars = false, |
|
dirty_shortcuts = false, |
|
} |
|
|
|
function XActionsHost:Init() |
|
self.actions = self.actions or {} |
|
self.shortcut_to_actions = {} |
|
self.menubar_actions = {} |
|
self.toolbar_actions = {} |
|
self.dirty_menubars = {} |
|
self.dirty_toolbars = {} |
|
self.dirty_shortcuts = {} |
|
|
|
for _, action in ipairs(self.actions) do |
|
action:RegisterInHost(self) |
|
end |
|
end |
|
|
|
function XActionsHost:ClearActions() |
|
if self.HostInParent then |
|
local host = GetActionsHost(self.parent) |
|
if host then |
|
for _, action in ipairs(host and self.actions) do |
|
host:RemoveAction(action) |
|
end |
|
end |
|
end |
|
table.clear(self.actions) |
|
table.clear(self.shortcut_to_actions) |
|
table.clear(self.menubar_actions) |
|
table.clear(self.toolbar_actions) |
|
end |
|
|
|
function XActionsHost:Done() |
|
self:ClearActions() |
|
end |
|
|
|
function XActionsHost:ActionsUpdated() |
|
if not self:GetThread("UpdateActionViews") then |
|
self:CreateThread("UpdateActionViews", self.UpdateActionViews, self, self) |
|
end |
|
end |
|
|
|
function XActionsHost:SetActionsMode(mode) |
|
if self.ActionsMode ~= mode then |
|
self.ActionsMode = mode |
|
self:ActionsUpdated() |
|
end |
|
end |
|
|
|
function XActionsHost:InvalidateActionSortKey(action) |
|
self.dirty_actions_order = true |
|
if action.ActionMenubar ~= "" then |
|
self.dirty_menubars[action.ActionMenubar] = true |
|
end |
|
if action.ActionToolbar ~= "" then |
|
self.dirty_toolbars[action.ActionToolbar] = true |
|
end |
|
if action.ActionShortcut ~= "" then |
|
self.dirty_shortcuts[action.ActionShortcut] = true |
|
end |
|
if action.ActionShortcut2 ~= "" then |
|
self.dirty_shortcuts[action.ActionShortcut2] = true |
|
end |
|
if action.ActionGamepad ~= "" then |
|
self.dirty_shortcuts[action.ActionGamepad] = true |
|
end |
|
end |
|
|
|
local function sort_actions(actions) |
|
table.stable_sort(actions, function(a,b) |
|
return a.ActionSortKey < b.ActionSortKey |
|
end) |
|
end |
|
|
|
function XActionsHost:GetActions() |
|
if self.dirty_actions_order then |
|
sort_actions(self.actions) |
|
self.dirty_actions_order = nil |
|
end |
|
return self.actions |
|
end |
|
|
|
function XActionsHost:GetMenubarActions(menubar) |
|
if self.dirty_menubars[menubar] then |
|
sort_actions(self.menubar_actions[menubar]) |
|
self.dirty_menubars[menubar] = nil |
|
end |
|
return self.menubar_actions[menubar] |
|
end |
|
|
|
function XActionsHost:GetToolbarActions(toolbar) |
|
if self.dirty_toolbars[toolbar] then |
|
sort_actions(self.toolbar_actions[toolbar]) |
|
self.dirty_toolbars[toolbar] = nil |
|
end |
|
return self.toolbar_actions[toolbar] |
|
end |
|
|
|
function XActionsHost:GetShortcutActions(shortcut) |
|
if self.dirty_shortcuts[shortcut] then |
|
sort_actions(self.shortcut_to_actions[shortcut]) |
|
self.dirty_shortcuts[shortcut] = nil |
|
end |
|
return self.shortcut_to_actions[shortcut] |
|
end |
|
|
|
function XActionsHost:CallHostParents(func, ...) |
|
self[func](self, ...) |
|
if self.HostInParent then |
|
local host = GetActionsHost(self.parent) |
|
if host then |
|
host:CallHostParents(func, ...) |
|
return |
|
end |
|
end |
|
end |
|
|
|
local function add_sorted(actions, action) |
|
actions = actions or {} |
|
local i = 1 |
|
local key = action.ActionSortKey |
|
local skip_add |
|
while i <= #actions and actions[i].ActionSortKey <= key do |
|
if actions[i] == action then |
|
|
|
skip_add = true |
|
break |
|
end |
|
i = i + 1 |
|
end |
|
if not skip_add then |
|
table.insert(actions, i, action) |
|
end |
|
return actions |
|
end |
|
|
|
function XActionsHost:AddShortcutToAction(action, shortcut) |
|
if (shortcut or "") == "" then return end |
|
|
|
self.shortcut_to_actions[shortcut] = add_sorted(self.shortcut_to_actions[shortcut], action) |
|
end |
|
|
|
function XActionsHost:RemoveShortcutToAction(action, shortcut) |
|
if (shortcut or "") == "" then return end |
|
local actions = self.shortcut_to_actions[shortcut] |
|
if not actions then return end |
|
table.remove_value(actions, action) |
|
end |
|
|
|
function XActionsHost:AddMenubarAction(action) |
|
local menubar = action.ActionMenubar |
|
if (menubar or "") == "" then return end |
|
self.menubar_actions[menubar] = add_sorted(self.menubar_actions[menubar], action) |
|
end |
|
|
|
function XActionsHost:RemoveMenubarAction(action) |
|
table.remove_entry(self.menubar_actions[action.ActionMenubar], action) |
|
end |
|
|
|
function XActionsHost:AddToolbarAction(action) |
|
local toolbar = action.ActionToolbar |
|
if (toolbar or "") == "" then return end |
|
self.toolbar_actions[toolbar] = add_sorted(self.toolbar_actions[toolbar], action) |
|
end |
|
|
|
function XActionsHost:RemoveToolbarAction(action) |
|
table.remove_entry(self.toolbar_actions[action.ActionToolbar], action) |
|
end |
|
|
|
function XActionsHost:_InternalAddAction(action, replace_matching_id) |
|
local actions = self.actions |
|
local key = action.ActionSortKey |
|
local old_idx = replace_matching_id and self:RemoveAction(self:ActionById(action.ActionId)) |
|
|
|
if old_idx and (old_idx == 1 or actions[old_idx - 1].ActionSortKey <= key) and |
|
(old_idx > #actions or actions[old_idx].ActionSortKey >= key) then |
|
table.insert(actions, old_idx, action) |
|
else |
|
|
|
add_sorted(actions, action) |
|
end |
|
|
|
|
|
self:AddMenubarAction(action) |
|
self:AddToolbarAction(action) |
|
|
|
|
|
self:AddShortcutToAction(action, action.ActionShortcut) |
|
self:AddShortcutToAction(action, action.ActionShortcut2) |
|
self:AddShortcutToAction(action, action.ActionGamepad) |
|
|
|
if self.HostInParent then |
|
local host = GetActionsHost(self.parent) |
|
if host then |
|
host:_InternalAddAction(action, replace_matching_id) |
|
return |
|
end |
|
end |
|
self:ActionsUpdated() |
|
|
|
end |
|
|
|
function XActionsHost:RemoveAction(action) |
|
if not action then return end |
|
local actions = self.actions |
|
local idx = table.remove_entry(self.actions, action) |
|
|
|
|
|
self:RemoveMenubarAction(action) |
|
self:RemoveToolbarAction(action) |
|
|
|
|
|
self:RemoveShortcutToAction(action, action.ActionShortcut) |
|
self:RemoveShortcutToAction(action, action.ActionShortcut2) |
|
self:RemoveShortcutToAction(action, action.ActionGamepad) |
|
|
|
if self.HostInParent then |
|
local host = GetActionsHost(self.parent) |
|
if host then |
|
host:RemoveAction(action) |
|
return |
|
end |
|
end |
|
self:ActionsUpdated() |
|
return idx |
|
end |
|
|
|
function XActionsHost:SetHostInParent(host_in_parent) |
|
if self.HostInParent == host_in_parent then return end |
|
self.HostInParent = host_in_parent |
|
local host = GetActionsHost(self.parent) |
|
if host then |
|
for _, action in ipairs(self.actions) do |
|
if host_in_parent then |
|
host:_InternalAddAction(action) |
|
else |
|
host:RemoveAction(action) |
|
end |
|
end |
|
end |
|
end |
|
|
|
function XActionsHost:ActionsSanityCheck() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
end |
|
|
|
function XActionsHost:UpdateActionViews(win) |
|
if Platform.developer then |
|
self:ActionsSanityCheck() |
|
end |
|
for _, win in ipairs(win) do |
|
if IsKindOf(win, "XActionsView") then |
|
win:OnUpdateActions() |
|
end |
|
if not IsKindOf(win, "XActionsHost") or win.HostInParent then |
|
self:UpdateActionViews(win) |
|
end |
|
end |
|
end |
|
|
|
function XActionsHost:ShowActionBar(bShow) |
|
local action_bar = self:HasMember("idActionBar") and self.idActionBar |
|
if action_bar then |
|
action_bar:SetVisible(bShow) |
|
end |
|
end |
|
|
|
function XActionsHost:FilterAction(action, action_context) |
|
if not action_context then |
|
return action:EnabledInMode(self.ActionsMode) and self:ActionState(action) ~= "hidden" |
|
end |
|
|
|
for _, context in ipairs(action.ActionContexts) do |
|
if context == action_context and self:ActionState(action) ~= "hidden" then |
|
return true |
|
end |
|
end |
|
return false |
|
end |
|
|
|
function XActionsHost:ActionState(action) |
|
local action_id = action.ActionId |
|
if action.OnActionEffect == "popup" and action.OnAction == XAction.OnAction and |
|
not self:HasMenubarActions(action_id) and not self:HasToolbarActions(action_id) then |
|
return "hidden" |
|
end |
|
return action:ActionState(self) |
|
end |
|
|
|
function XActionsHost:HasMenubarActions(action_id) |
|
return next(self.menubar_actions[action_id]) |
|
end |
|
|
|
function XActionsHost:HasToolbarActions(action_id) |
|
return next(self.toolbar_actions[action_id]) |
|
end |
|
|
|
function XActionsHost:OnAction(action, ctrl, ...) |
|
local hasFx = ctrl and ctrl.FXPress |
|
local ret = action:OnAction(self, ctrl, ...) |
|
if #(action.FXPress or "") ~= 0 and not hasFx then PlayFX(action.FXPress, "start", action) end |
|
if action.ActionToggle then |
|
self:ActionsUpdated() |
|
end |
|
Msg("XActionActivated", self, action, ctrl, ...) |
|
return ret |
|
end |
|
|
|
function XActionsHost:ActionById(id) |
|
return table.find_value(self.actions, "ActionId", id) |
|
end |
|
|
|
function XActionsHost:IsActionShortcut(id, shortcut) |
|
local action = self:ActionById(id) |
|
if not action then return end |
|
return action.ActionShortcut == shortcut or action.ActionShortcut2 == shortcut or action.ActionGamepad == shortcut |
|
end |
|
|
|
function XActionsHost:ActionByShortcut(shortcut, input, controller_id, repeated, ...) |
|
local found |
|
for _, action in ipairs(self:GetShortcutActions(shortcut)) do |
|
if (not action.IgnoreRepeated or not repeated) then |
|
if self:FilterAction(action) then |
|
local state = action:ActionState(self) |
|
if state ~= "disabled" and state ~= "hidden" then |
|
found = action |
|
break |
|
end |
|
end |
|
end |
|
end |
|
|
|
return found |
|
end |
|
|
|
function XActionsHost:GamepadHoldActionByShortcut(shortcut) |
|
local found |
|
for _, action in ipairs(self:GetShortcutActions(shortcut)) do |
|
if action.ActionGamepadHold and self:FilterAction(action) then |
|
local state = action:ActionState(self) |
|
if state ~= "disabled" and state ~= "hidden" then |
|
found = action |
|
break |
|
end |
|
end |
|
end |
|
return found |
|
end |
|
|
|
if FirstLoad then |
|
KbdShortcutToRelation = { |
|
["Tab"] = "next", |
|
["Shift-Tab"] = "prev", |
|
["Up"] = "up", |
|
["Down"] = "down", |
|
["Left"] = "left", |
|
["Right"] = "right", |
|
} |
|
|
|
XShortcutToRelation = { |
|
["LeftThumbLeft"] = "left", ["LeftThumbDownLeft"] = "left", ["LeftThumbUpLeft"] = "left", |
|
["LeftThumbRight"] = "right", ["LeftThumbDownRight"] = "right", ["LeftThumbUpRight"] = "right", |
|
["LeftThumbUp"] = "up", |
|
["LeftThumbDown"] = "down", |
|
["DPadLeft"] = "left", |
|
["DPadRight"] = "right", |
|
["DPadUp"] = "up", |
|
["DPadDown"] = "down", |
|
} |
|
end |
|
|
|
function XActionsHost:OnHoldDown(pt, button) |
|
local action = self:GamepadHoldActionByShortcut(button) |
|
action:OnAction(self,button) |
|
end |
|
|
|
function XActionsHost:OnHoldButtonTick(i, shortcut) |
|
local action = self:GamepadHoldActionByShortcut(shortcut) |
|
if not action then |
|
return |
|
end |
|
local ctrl = self.action_hold_buttons and self.action_hold_buttons[action.ActionId] |
|
if ctrl and ctrl:HasMember("OnHoldButtonTick") then |
|
ctrl:OnHoldButtonTick(i) |
|
else |
|
XHoldButton.OnHoldButtonTick(self, i, shortcut) |
|
end |
|
end |
|
|
|
function XActionsHost:OnXButtonRepeat(shortcut, controller_id,...) |
|
if self.HostInParent then return end |
|
if not RepeatableXButtons[shortcut] then |
|
local found = self:GamepadHoldActionByShortcut(shortcut) |
|
if found then |
|
XHoldButton.OnHoldButtonRepeat(self,shortcut, controller_id) |
|
return "break" |
|
end |
|
end |
|
end |
|
|
|
function XActionsHost:OnShortcut(shortcut, source, controller_id, ...) |
|
if self.HostInParent then return end |
|
local found |
|
if source=="gamepad" then |
|
if shortcut:starts_with("-") then |
|
local org_shortcut = shortcut:gsub("-", "") |
|
found = self:GamepadHoldActionByShortcut(org_shortcut) |
|
if found then |
|
found = XHoldButton.OnHoldButtonUp(self, org_shortcut, controller_id) |
|
if found then |
|
return "break" |
|
end |
|
end |
|
elseif shortcut:starts_with("+") then |
|
local org_shortcut = shortcut:gsub("+", "") |
|
found = self:GamepadHoldActionByShortcut(org_shortcut) |
|
if found then |
|
XHoldButton.OnHoldButtonDown(self,org_shortcut, controller_id) |
|
end |
|
else |
|
found = self:GamepadHoldActionByShortcut(shortcut) |
|
if found then |
|
XHoldButton.OnHoldButtonRepeat(self,shortcut, controller_id) |
|
end |
|
end |
|
end |
|
local action = not found and self:ActionByShortcut(shortcut, source, controller_id, ...) |
|
if action then |
|
self:OnAction(action, source, controller_id, ...) |
|
return "break" |
|
end |
|
if source ~= "mouse" then |
|
local relation = (source == "keyboard") and KbdShortcutToRelation[shortcut] or XShortcutToRelation[shortcut] |
|
if relation then |
|
local focus = self.desktop and self.desktop.keyboard_focus |
|
local order = focus and focus:IsWithin(self) and focus:GetFocusOrder() or point(0, 0) |
|
focus = self:GetRelativeFocus(order, relation) |
|
if focus then |
|
|
|
CreateRealTimeThread(function() |
|
if focus.window_state ~= "destroying" then |
|
focus:SetFocus() |
|
if source == "gamepad" and RolloverControl ~= focus then |
|
XCreateRolloverWindow(focus, true) |
|
end |
|
end |
|
end) |
|
return "break" |
|
end |
|
end |
|
end |
|
end |
|
|
|
function XActionsHost:OpenContextMenu(action_context, anchor_pt) |
|
if not action_context or not anchor_pt or action_context == "" then return end |
|
local menu = XPopupMenu:new({ |
|
ActionContextEntries = action_context, |
|
Anchor = anchor_pt, |
|
AnchorType = "mouse", |
|
MaxItems = 12, |
|
GetActionsHost = function() return self end, |
|
popup_parent = self, |
|
}, terminal.desktop) |
|
menu:Open() |
|
return menu |
|
end |
|
|
|
function XActionsHost:OpenPopupMenu(menubar_id, anchor_pt) |
|
local menu = XPopupMenu:new({ |
|
MenuEntries = menubar_id, |
|
Anchor = anchor_pt, |
|
AnchorType = "mouse", |
|
MaxItems = 12, |
|
GetActionsHost = function() return self end, |
|
popup_parent = self, |
|
}, terminal.desktop) |
|
menu:Open() |
|
return menu |
|
end |
|
|
|
|
|
|
|
|
|
DefineClass.XActionsView = { |
|
__parents = { "XContextWindow" }, |
|
properties = { |
|
{ category = "General", id = "HideWithoutActions", name = "Hide without actions", editor = "bool", default = false }, |
|
} |
|
} |
|
|
|
function XActionsView:GetActionsHost() |
|
return GetActionsHost(self, true) |
|
end |
|
|
|
function XActionsView:Open(...) |
|
XContextWindow.Open(self, ...) |
|
self:OnUpdateActions() |
|
end |
|
|
|
function XActionsView:PopupAction(action_id, host, source) |
|
assert(false) |
|
end |
|
|
|
function XActionsView:OnUpdateActions() |
|
local host = self:GetActionsHost() |
|
if not host or self.window_state == "new" then return end |
|
self:RebuildActions(host) |
|
if self.HideWithoutActions then |
|
self:SetVisible(#self > 0) |
|
end |
|
Msg("XWindowRecreated", self) |
|
end |
|
|
|
function XActionsView:RebuildActions(host) |
|
end |
|
|
|
|
|
|
|
|
|
function GetActionsHost(win, final) |
|
while win and (not win:IsKindOf("XActionsHost") or win.HostInParent and final) do |
|
win = win.parent |
|
if final and win and win:IsKindOf("XActionsView") then |
|
return win:GetActionsHost() |
|
end |
|
end |
|
return win |
|
end |
|
|
|
function EnabledInModes(givenModes, modes) |
|
if givenModes == "" or modes == "" or modes == givenModes then return true end |
|
|
|
for givenMode in string.gmatch(givenModes, "([%w%-_]+)") do |
|
for mode in string.gmatch(modes, "([%w%-_]+)") do |
|
if givenMode == mode or givenMode == "ForwardToC" or mode == "ForwardToC" then |
|
return true |
|
end |
|
end |
|
end |
|
|
|
return false |
|
end |
|
|