myspace / CommonLua /X /XButton.lua
sirnii's picture
Upload 1816 files
b6a38d7 verified
raw
history blame
16.3 kB
DefineClass.XButton = {
__parents = { "XContextControl" },
properties = {
{ category = "General", id = "RepeatStart", name = "Start repeating time", editor = "number", default = 0, },
{ category = "General", id = "RepeatInterval", name = "Repeat interval", editor = "number", default = 0, },
{ category = "General", id = "OnPressEffect", editor = "choice", default= "", items = {"", "close", "action"}, },
{ category = "General", id = "OnPressParam", editor = "text", default = "" },
{ category = "General", id = "OnPress", name = "On press", editor = "func", params = "self, gamepad" },
{ category = "General", id = "AltPress", name = "Allow alternative press", editor = "bool", default = false, },
{ category = "General", id = "OnAltPress", name = "On alt press", editor = "func", params = "self, gamepad" },
{ category = "Visual", id = "RolloverBackground", name = "Rollover background", editor = "color", default = RGBA(255, 255, 255, 255), },
{ category = "Visual", id = "RolloverBorderColor", name = "Rollover border color", editor = "color", default = RGBA(0, 0, 0, 0), },
{ category = "Visual", id = "PressedBackground", name = "Pressed background", editor = "color", default = RGBA(255, 255, 255, 255), },
{ category = "Visual", id = "PressedBorderColor", name = "Pressed border color", editor = "color", default = RGBA(0, 0, 0, 0), },
{ category = "Visual", id = "PressedOffset", name = "Pressed offset", editor = "number", default = 1, },
},
Background = RGBA(255, 255, 255, 255),
FocusedBackground = RGBA(255, 255, 255, 255),
MouseCursor = "CommonAssets/UI/HandCursor.tga",
state = "mouse-out",
ChildrenHandleMouse = false,
RolloverOnFocus = true,
action = false,
touch_press_dist = 20*20, -- square for max move distance before press
AltPressButton = "ButtonX",
AltPressButtonUp = "-ButtonX",
AltPressButtonDown = "+ButtonX",
}
function XButton:Open(...)
local host = GetActionsHost(self, true)
if not self.action and self.OnPressEffect == "action" then
self.action = host and host:ActionById(self.OnPressParam) or nil
end
if self:IsActionDisabled(host) then
self:SetEnabled(false)
end
if self.action and self.action.ActionGamepadHold and self.action.ActionGamepad then
host.action_hold_buttons = host.action_hold_buttons or {}
host.action_hold_buttons[self.action.ActionId] = self
end
if self.action and self.action.OnAltAction then
self.AltPress = true
end
XContextControl.Open(self, ...)
end
function XButton:IsActionDisabled(host, ...)
return self.action and self.action:ActionState(host, ...) == "disabled"
end
function XButton:Press(alt, force, gamepad)
if alt and not self.AltPress then return end
self:PlayActionFX(force)
if not self.enabled and not force then
return
end
if alt then
self:OnAltPress(gamepad)
else
self:OnPress(gamepad)
end
if self.window_state ~= "destroying" then
local host = GetActionsHost(self, true)
if self:IsActionDisabled(host) then
self:SetEnabled(false)
end
end
end
function XButton:OnPress(gamepad)
local effect = self.OnPressEffect
if effect == "close" then
local win = self.parent
while win and not win:IsKindOf("XDialog") do
win = win.parent
end
if win then
win:Close(self.OnPressParam ~= "" and self.OnPressParam or nil)
end
elseif self.action then
local host = GetActionsHost(self, true)
if host then
host:OnAction(self.action, self, gamepad)
end
end
end
function XButton:OnAltPress(gamepad)
if self.action and self.action.OnAltAction then
local host = GetActionsHost(self, true)
if host then
self.action:OnAltAction(host, self, gamepad)
end
end
end
function XButton:OnButtonDown(alt, mouse)
if alt and not self.AltPress then return end
if not self.enabled then
self:Press(alt, nil, not mouse) --play sound FX
return "break"
end
if self.state == "mouse-in" or self.state == "mouse-out" then
self.state = "pressed-in"
if mouse then
self.desktop:SetMouseCapture(self)
end
self:Invalidate()
if self.RepeatStart > 0 then
self:DeleteThread("repeat")
self:CreateThread("repeat", function(self, alt)
Sleep(self.RepeatStart)
while self.state == "pressed-in" or self.state == "pressed-out" do
self:Press(alt, nil, not mouse)
Sleep(self.RepeatInterval)
end
end, self, alt)
end
end
return "break"
end
function XButton:OnButtonUp(alt, mouse)
if alt and not self.AltPress then return end
if self.state == "pressed-in" then
self.state = "mouse-in"
self:Invalidate()
if mouse then
self.desktop:SetMouseCapture()
end
self:Press(alt, nil, not mouse)
elseif self.state == "pressed-out" then
self.state = "mouse-out"
self:Invalidate()
if mouse then
self.desktop:SetMouseCapture()
end
end
return "break"
end
function XButton:OnMouseButtonDown(pt, button)
if button == "L" then
return self:OnButtonDown(false, true)
elseif button == "R" then
return self:OnButtonDown(true, true)
end
end
function XButton:OnMouseButtonUp(pt, button)
if button == "L" then
return self:OnButtonUp(false, true)
elseif button == "R" then
return self:OnButtonUp(true, true)
end
end
function XButton:OnSetRollover(rollover)
XControl.OnSetRollover(self, rollover)
if rollover then
if self.state == "mouse-out" then
self.state = "mouse-in"
elseif self.state == "pressed-out" then
self.state = "pressed-in"
end
else
if self.state == "mouse-in" then
self.state = "mouse-out"
elseif self.state == "pressed-in" then
self.state = "pressed-out"
end
end
self:Invalidate()
end
function XButton:OnCaptureLost()
if self.state == "pressed-in" then
self.state = "mouse-in"
elseif self.state == "pressed-out" then
self.state = "mouse-out"
end
self:Invalidate()
end
-- touch
function XButton:OnTouchBegan(id, pos, touch)
if self.state == "mouse-in" or self.state == "mouse-out" then
touch.start_pos = pos
touch.start_time = RealTime()
self.state = "pressed-out"
self:OnTouchMoved(id, pos, touch)
return "capture"
end
end
function XButton:OnTouchMoved(id, pos, touch)
if touch.capture == self then
local dist_diff = pos:Dist2D2(touch.start_pos)
if dist_diff > self.touch_press_dist then
-- if there is an ancestor of type XScrollArea, allow it to be scrolled
local scroll_area = GetParentOfKind(self, "XScrollArea")
if scroll_area then
self:OnTouchCancelled(id, pos, touch)
touch.capture = nil -- release capture
touch.target = scroll_area -- target is now the scroll area
return scroll_area:OnTouchBegan(id, pos, touch)
end
end
if self.state == "pressed-in" and not self:PointInWindow(pos) then
self.state = "pressed-out"
self:Invalidate()
self:PlayHoverFX(false)
elseif self.state == "pressed-out" and self:PointInWindow(pos) then
self.state = "pressed-in"
self:Invalidate()
self:PlayHoverFX(true)
end
return "break"
end
end
function XButton:OnTouchEnded(id, pos, touch)
self:OnTouchMoved(id, pos, touch)
if self.state == "pressed-in" then
self:Press(false)
end
return self:OnTouchCancelled(id, pos, touch)
end
function XButton:OnTouchCancelled(id, pos, touch)
if self.state ~= "mouse-out" then
if self.state == "pressed-in" then
self:PlayHoverFX(false)
end
self.state = "mouse-out"
self:Invalidate()
return "break"
end
end
function XButton:OnShortcut(shortcut, source, ...)
if shortcut == "Enter" or shortcut == "Space" or shortcut == "ButtonA" then
self:Press(false)
return "break"
elseif self.AltPress and (shortcut == "Alt-Enter" or shortcut == "Alt-Space" or shortcut == self.AltPressButton) then
self:Press(true)
return "break"
elseif shortcut == "+ButtonA" then
return self:OnButtonDown(false)
elseif shortcut == self.AltPressButtonDown then
return self:OnButtonDown(true)
elseif shortcut == "-ButtonA" then
return self:OnButtonUp(false)
elseif shortcut == self.AltPressButtonUp then
return self:OnButtonUp(true)
end
end
function XButton:CalcBackground()
if not self.enabled then return self.DisabledBackground end
if self.state == "pressed-in" or self.state == "pressed-out" then
return self.PressedBackground
end
if self.state == "mouse-in" then
return self.RolloverBackground
end
local FocusedBackground, Background = self.FocusedBackground, self.Background
if FocusedBackground == Background then return Background end
return self:IsFocused() and FocusedBackground or Background
end
function XButton:CalcBorderColor()
if not self.enabled then return self.DisabledBorderColor end
if self.state == "pressed-in" or self.state == "pressed-out" then
return self.PressedBorderColor
end
if self.state == "mouse-in" then
return self.RolloverBorderColor
end
local FocusedBorderColor, BorderColor = self.FocusedBorderColor, self.BorderColor
if FocusedBorderColor == BorderColor then return BorderColor end
return self:IsFocused() and FocusedBorderColor or BorderColor
end
function XButton:GetRolloverTemplate()
local template = self.RolloverTemplate
if template ~= "" then return template end
local action = self.action
return action and action:GetRolloverTemplate() or ""
end
function XButton:GetRolloverText()
local enabled = self:GetEnabled()
local text = not enabled and self.RolloverDisabledText ~= "" and self.RolloverDisabledText or self.RolloverText
if text ~= "" then return text end
local action = self.action
local disabled_text = action and action:GetRolloverDisabledText()
return action and (not enabled and disabled_text ~= "" and disabled_text or action:GetRolloverText()) or ""
end
function OnMsg.ClassesPostprocess()
if not config.GamepadAltPressUseButtonY then return end
ClassDescendants("XButton", function(class_name, class)
class.AltPressButton = "ButtonY"
class.AltPressButtonUp = "-ButtonY"
class.AltPressButtonDown = "+ButtonY"
end)
XButton.AltPressButton = "ButtonY"
XButton.AltPressButtonUp = "-ButtonY"
XButton.AltPressButtonDown = "+ButtonY"
end
----- XTextButton
DefineClass.XTextButton = {
__parents = { "XButton", "XFrame", "XEmbedIcon", "XEmbedLabel" },
properties = {
{ category = "Image", id = "ColumnsUse", editor = "text", default = "aaaaa", }, -- 'help' is generated below
{ category = "Image", id = "ShowGamepadShortcut", editor = "bool", default = false, },
{ category = "Visual", id = "ShowKeyboardShortcut", editor = "bool", default = false, },
{ category = "Visual", id = "KeyboardShortcutTextStyle", editor = "text", default = "", },
},
ContextUpdateOnOpen = true,
LayoutMethod = "HList",
LayoutHSpacing = 2,
HandleMouse = true,
SqueezeX = false,
SqueezeY = false,
}
function XTextButton:Init()
self.idLabel:SetHAlign("center")
self:SetColumnsUse(self.ColumnsUse)
end
function XTextButton:OnHoldButtonTick(i, shortcut)
if not self.action or not self.action.ActionGamepadHold then return end
self.idHoldShortcut:SetVisible(not not i)
if i then
self.idHoldShortcut:SetImage("UI/DesktopGamepad/hold" .. i)
end
end
function XTextButton:Open()
XButton.Open(self)
local action = self.action
if action then
local action_ui_style = action.ActionUIStyle
if self.ShowGamepadShortcut and (action_ui_style == "auto" and GetUIStyleGamepad() or action_ui_style == "gamepad") and action.ActionGamepad ~= "" then
local keys = SplitShortcut(action.ActionGamepad)
for i = 1, #keys do
local image_path, scale = GetPlatformSpecificImagePath(keys[i])
local img = XImage:new({
Id = "idActionShortcut",
Image = image_path,
ZOrder = 0,
ImageScale = point(scale, scale),
enabled = self.enabled,
}, self)
if action.ActionGamepadHold then
local over_img = XImage:new({
Id = "idHoldShortcut",
Image = "UI/DesktopGamepad/hold0",
ZOrder = 0,
ImageScale = point(scale, scale),
enabled = self.enabled,
}, self)
end
img:Open()
if action.ActionGamepadHold then
over_img:Open()
end
end
elseif self.ShowKeyboardShortcut and (action_ui_style == "auto" and not GetUIStyleGamepad() or action_ui_style == "keyboard") and action.ActionShortcut ~= "" then
local label = XLabel:new({
Id = "idActionShortcut",
ZOrder = 0,
TextStyle = self.KeyboardShortcutTextStyle ~= "" and self.KeyboardShortcutTextStyle or self.TextStyle,
VAlign = "center",
Translate = true,
enabled = self.enabled,
}, self):Open()
local name = KeyNames[VKStrNamesInverse[action.ActionShortcut]]
label:SetText(T{629765447024, "<name>", name = name})
end
end
end
function XTextButton:SetText(text)
self.Text = text
local label = self:ResolveId("idLabel")
if label then
label:SetDock(text == "" and "ignore" or false)
label:SetText(text)
end
end
local a_charcode = string.byte("a")
function XTextButton:SetColumnsUse(columns_use)
local max = 1
for i = 1, #columns_use do
max = Max(max, string.byte(columns_use, i))
end
self.ColumnsUse = columns_use
self.Columns = max - a_charcode + 1
self:Invalidate()
end
function XTextButton:SetColumn()
assert(false)
end
function XTextButton:SetRollover(rollover)
XButton.SetRollover(self, rollover)
local label = self:ResolveId("idLabel")
if label then
label:SetRollover(rollover)
end
end
function XTextButton:OnSetRollover(rollover)
XButton.OnSetRollover(self, rollover)
end
local state_to_column = {
["mouse-out" ] = 1,
["mouse-in" ] = 2,
["pressed-out"] = 3,
["pressed-in" ] = 4,
["disabled" ] = 5,
}
function XTextButton:GetColumn()
local column = state_to_column[self.enabled and self.state or "disabled"]
return (string.byte(self.ColumnsUse, column) or a_charcode) - a_charcode + 1
end
do
local columns_use_prop = table.find_value(XTextButton.properties, "id", "ColumnsUse")
local column_to_state = table.invert(state_to_column)
columns_use_prop.help = ""
for i=1,#column_to_state do
columns_use_prop.help = string.format("%s%d - %s\n", columns_use_prop.help, i, column_to_state[i])
end
end
----- XStateButton
DefineClass.XStateButton = {
__parents = { "XTextButton" },
TextColor = RGB(32, 32, 32),
IconColor = RGB(32, 32, 32),
DisabledTextColor = RGBA(32, 32, 32, 128),
DisabledIconColor = RGBA(32, 32, 32, 128),
Icon = "CommonAssets/UI/check-40.tga",
IconScale = point(480, 480),
IconRows = 2,
}
function XStateButton:OnRowChange(row)
end
function XStateButton:OnPress()
local row = self.IconRow + 1
if row > self.IconRows then
row = 1
end
self:SetIconRow(row)
self:OnRowChange(row)
XTextButton.OnPress(self)
end
----- XCheckButton
DefineClass.XCheckButton = {
__parents = { "XStateButton" },
properties = {
{ category = "General", id = "Check", editor = "bool", default = false, },
{ category = "General", id = "OnChange", name = "On change", editor = "func", params = "self, check" },
},
Background = RGBA(0, 0, 0, 0),
RolloverBackground = RGBA(0, 0, 0, 0),
FocusedBackground = RGBA(0, 0, 0, 0),
PressedBackground = RGBA(0, 0, 0, 0),
}
function XCheckButton:SetCheck(check)
self:SetIconRow(check and 2 or 1)
end
function XCheckButton:GetCheck()
return self.IconRow ~= 1
end
XCheckButton.SetToggled = XCheckButton.SetCheck
function XCheckButton:OnChange(check)
end
function XCheckButton:OnRowChange(state)
self:OnChange(state ~= 1)
end
----- XToggleButton
DefineClass.XToggleButton = {
__parents = { "XTextButton" },
properties = {
{ category = "General", id = "Toggled", editor = "bool", default = false, },
{ category = "General", id = "OnChange", name = "On change", editor = "func", params = "self, toggled" },
{ category = "Visual", id = "ToggledBackground", name = "Toggled background", editor = "color", default = RGBA(0, 0, 0, 0), },
{ category = "Visual", id = "ToggledBorderColor", name = "Toggled border color", editor = "color", default = RGBA(0, 0, 0, 0), },
},
}
function XToggleButton:OnPress()
self:SetToggled(not self.Toggled)
XTextButton.OnPress(self)
end
function XToggleButton:SetToggled(toggled)
toggled = toggled or false
if self.Toggled ~= toggled then
self.Toggled = toggled
self:OnChange(self.Toggled)
self:Invalidate()
end
end
function XToggleButton:OnChange(toggled)
end
function XToggleButton:CalcBackground()
return self.Toggled and self.ToggledBackground or XTextButton.CalcBackground(self)
end
function XToggleButton:CalcBorderColor()
return self.Toggled and self.ToggledBorderColor or XTextButton.CalcBorderColor(self)
end