Compare commits

..

No commits in common. "main" and "2.24" have entirely different histories.
main ... 2.24

32 changed files with 3880 additions and 185 deletions

3
.drone.status Normal file
View File

@ -0,0 +1,3 @@
{
"url": "https://drone.f-brinker.de/fbrinker/elderscrolls-addon-achievementInfo/"
}

58
.drone.yml Normal file
View File

@ -0,0 +1,58 @@
---
kind: pipeline
name: default
clone:
disable: true
steps:
- name: clone
image: alpine/git
commands:
- git clone https://git.f-brinker.de/fbrinker/elderscrolls-addon-achievementInfo.git sources
- cd sources && git checkout $DRONE_COMMIT
- name: lint
image: alpine
commands:
- apk update
- apk add --no-cache build-base curl unzip
- apk add --no-cache lua5.1 lua5.1-dev luarocks5.1
- luarocks-5.1 install luacheck
- cd sources
- luacheck ./*.lua
- name: build
image: alpine
commands:
- apk update && apk add --no-cache zip
# Delete unneeded files/dirs
- rm -rf sources/.git
- rm -f sources/.drone.status
- rm -f sources/.drone.yml
- rm -f sources/.luacheckrc
# Set Version and AddonVersion
- export VERSION=$DRONE_TAG
- export ADDON_VERSION=$(echo $DRONE_TAG | sed -E 's/(0|)\.//g')
- sed -i "s/0.123456789/$VERSION/g" sources/AchievementInfoCommon.lua
- sed -i "s/0.123456789/$VERSION/g" sources/AchievementInfo.txt
- sed -i "s/0.123456789/$ADDON_VERSION/g" sources/AchievementInfo.txt
# Rename and zip
- mv sources AchievementInfo
- zip -r "AchievementInfo-$DRONE_TAG.zip" ./AchievementInfo
when:
event:
- tag
- name: release
image: plugins/gitea-release
settings:
base_url: https://git.f-brinker.de
api_key:
from_secret: gitea_token
files: ./*.zip
title: AchievementInfo ${DRONE_TAG}
note: AchievementInfo/CHANGELOG.md
when:
event:
- tag

View File

@ -1,55 +0,0 @@
name: Workflow
run-name: ${{ gitea.actor }} is linting and creating a new release on tag pushes 🚀
on: [push]
jobs:
Linting:
runs-on: ubuntu-latest
steps:
- name: Check out repository code
uses: actions/checkout@v4
- name: Run Luacheck linter
uses: lunarmodules/luacheck@v1
Release:
needs: [Linting]
if: ${{ startsWith(github.ref, 'refs/tags/') }} # only for tags
runs-on: ubuntu-latest
env:
Version: ${{ gitea.ref_name }}
steps:
- name: Check out repository code
uses: actions/checkout@v4
with:
path: sources
- name: Delete unneeded files/dirs
run: |
rm -rf sources/.git
rm -rf sources/.gitea
rm -rf sources/screenshots
rm -f sources/.luacheckrc
- name: Set Version and AddonVersion
run: |
echo "Version: ${{ env.Version }}"
export ADDON_VERSION=$(echo ${{ env.Version }} | sed -E 's/(0|)\.//g')
sed -i "s/0.123456789/${{ env.Version }}/g" sources/AchievementInfoCommon.lua
sed -i "s/0.123456789/${{ env.Version }}/g" sources/AchievementInfo.txt
sed -i "s/0.123456789/$ADDON_VERSION/g" sources/AchievementInfo.txt
- name: Rename and zip
run: |
mv sources AchievementInfo
zip -r "AchievementInfo-${{ env.Version }}.zip" ./AchievementInfo
- name: Create release
id: create_release
uses: akkuman/gitea-release-action@v1
with:
token: ${{ secrets.token }}
name: "AchievementInfo ${{ env.Version }}"
tag_name: "${{ env.Version }}"
body_path: AchievementInfo/CHANGELOG.md
draft: false
prerelease: false
sha256sum: true
files: |-
*.zip

View File

@ -17,8 +17,7 @@ read_globals = {
"EVENT_ACHIEVEMENT_UPDATED", "EVENT_ACHIEVEMENT_UPDATED",
"EVENT_ADD_ON_LOADED", "EVENT_ADD_ON_LOADED",
"EVENT_MANAGER", "EVENT_MANAGER",
"LINK_STYLE_BRACKETS", "LINK_STYLE_BRACKET",
"zo_callLater", "zo_callLater",
"zo_strformat",
"ZO_SavedVars", "ZO_SavedVars",
} }

View File

@ -15,7 +15,6 @@ function AchievementInfo.initialize(_, addOnName)
AchievementInfo.hijackedFirstLoad = true AchievementInfo.hijackedFirstLoad = true
-- Load Saved Variables -- Load Saved Variables
AchievementInfo.useAccountWideSettings = AchievementInfo.loadUseAccountWideSettings()
AchievementInfo.savedVars = AchievementInfo.loadSavedVars() AchievementInfo.savedVars = AchievementInfo.loadSavedVars()
-- Load Language Data -- Load Language Data

View File

@ -5,10 +5,13 @@
## Author: |c87B7CCAsto|r, @Astarax ## Author: |c87B7CCAsto|r, @Astarax
## Contact: mail@coded-with-heart.com ## Contact: mail@coded-with-heart.com
## APIVersion: 101044 ## APIVersion: 100029
## SavedVariables: ACHIEVEMENT_INFO_DB ACHIEVEMENT_INFO_DB_USE_AW ## SavedVariables: ACHIEVEMENT_INFO_DB
## DependsOn: LibAddonMenu-2.0 ## OptionalDependsOn: LibAddonMenu-2.0
## Libraries:
Libs/LibAddonMenu-2.0/LibAddonMenu-2.0.lua
## Helper: ## Helper:
AchievementInfoCommon.lua AchievementInfoCommon.lua

View File

@ -49,7 +49,7 @@ function AchievementInfo.onAchievementUpdated(_, achId)
local percentageStep = false local percentageStep = false
local percentageStepSize = AchievementInfo.settingGet("genShowUpdateSteps") local percentageStepSize = AchievementInfo.settingGet("genShowUpdateSteps")
local link = GetAchievementLink(achId, LINK_STYLE_BRACKETS) local link = GetAchievementLink(achId, LINK_STYLE_BRACKET)
local catName = "/" local catName = "/"
if categoryId ~= false then if categoryId ~= false then
@ -67,18 +67,13 @@ function AchievementInfo.onAchievementUpdated(_, achId)
tmpOutput = tmpOutput .. ", " tmpOutput = tmpOutput .. ", "
end end
tmpOutput = tmpOutput .. zo_strformat("<<1>>", description) .. " " tmpOutput = tmpOutput .. description .. " "
tmpOutput = tmpOutput .. AchievementInfo.calcCriteriaColor(numCompleted, numRequired) .. numCompleted .. "|r" tmpOutput = tmpOutput .. AchievementInfo.calcCriteriaColor(numCompleted, numRequired) .. numCompleted .. "|r"
tmpOutput = tmpOutput .. AchievementInfo.clrDefault .. "/" .. "|r" tmpOutput = tmpOutput .. AchievementInfo.clrDefault .. "/" .. "|r"
tmpOutput = tmpOutput .. AchievementInfo.clrCriteriaComplete .. numRequired .. "|r" tmpOutput = tmpOutput .. AchievementInfo.clrCriteriaComplete .. numRequired .. "|r"
tmpOutput = tmpOutput .. AchievementInfo.clrDefault tmpOutput = tmpOutput .. AchievementInfo.clrDefault
if AchievementInfo.settingGet("genShowOpenDetailsOnly") == true then if AchievementInfo.settingGet("genShowOpenDetailsOnly") == true and numCompleted ~= numRequired then
if numCompleted ~= numRequired then
detailOutput[detailOutputCount] = tmpOutput
detailOutputCount = detailOutputCount + 1
end
else
detailOutput[detailOutputCount] = tmpOutput detailOutput[detailOutputCount] = tmpOutput
detailOutputCount = detailOutputCount + 1 detailOutputCount = detailOutputCount + 1
end end

View File

@ -35,9 +35,6 @@ LANG_STORE.EN.SettingsOption.AddOnEnabled = "AddOn enabled"
LANG_STORE.EN.SettingsOption.AddOnEnabledTooltip = "Enable or disable this AddOn" LANG_STORE.EN.SettingsOption.AddOnEnabledTooltip = "Enable or disable this AddOn"
LANG_STORE.EN.SettingsOption.AddOnEnabledWarning = "Only the output messages can be disabled here" LANG_STORE.EN.SettingsOption.AddOnEnabledWarning = "Only the output messages can be disabled here"
LANG_STORE.EN.SettingsOption.AccountWideEnabled = "Use account-wide Settings"
LANG_STORE.EN.SettingsOption.AccountWideEnabledTooltip = "Use and edit the same settings for all characters"
LANG_STORE.EN.SettingsOption.ShowEveryUpdate = "Show every update" LANG_STORE.EN.SettingsOption.ShowEveryUpdate = "Show every update"
LANG_STORE.EN.SettingsOption.ShowEveryUpdateTooltip = "Shows a message on every status update of an achievement. Otherwise the messages appear only in steps of x%" LANG_STORE.EN.SettingsOption.ShowEveryUpdateTooltip = "Shows a message on every status update of an achievement. Otherwise the messages appear only in steps of x%"
@ -89,9 +86,6 @@ LANG_STORE.DE.SettingsOption.AddOnEnabled = "AddOn aktiviert"
LANG_STORE.DE.SettingsOption.AddOnEnabledTooltip = "Aktiviere oder deaktiviere dieses AddOn" LANG_STORE.DE.SettingsOption.AddOnEnabledTooltip = "Aktiviere oder deaktiviere dieses AddOn"
LANG_STORE.DE.SettingsOption.AddOnEnabledWarning = "An dieser Stelle können nur die Ausgaben deaktiviert werden." LANG_STORE.DE.SettingsOption.AddOnEnabledWarning = "An dieser Stelle können nur die Ausgaben deaktiviert werden."
LANG_STORE.DE.SettingsOption.AccountWideEnabled = "Accountübergreifende Einstellungen"
LANG_STORE.DE.SettingsOption.AccountWideEnabledTooltip = "Benutze und speichere die Einstellungen für alle Charaktere"
LANG_STORE.DE.SettingsOption.ShowEveryUpdate = "Zeige alle Fortschritte" LANG_STORE.DE.SettingsOption.ShowEveryUpdate = "Zeige alle Fortschritte"
LANG_STORE.DE.SettingsOption.ShowEveryUpdateTooltip = "Zeigt bei jeder Aktualisierung eines Erfolgs einen Hinweis. Alternativ wird nur in x% Schritten ein Status ausgegeben" LANG_STORE.DE.SettingsOption.ShowEveryUpdateTooltip = "Zeigt bei jeder Aktualisierung eines Erfolgs einen Hinweis. Alternativ wird nur in x% Schritten ein Status ausgegeben"
@ -144,9 +138,6 @@ LANG_STORE.FR.SettingsOption.AddOnEnabled = "Extension activée"
LANG_STORE.FR.SettingsOption.AddOnEnabledTooltip = "Active ou désactive cette extension" LANG_STORE.FR.SettingsOption.AddOnEnabledTooltip = "Active ou désactive cette extension"
LANG_STORE.FR.SettingsOption.AddOnEnabledWarning = "Seul les messages sortants peuvent être désactivés" LANG_STORE.FR.SettingsOption.AddOnEnabledWarning = "Seul les messages sortants peuvent être désactivés"
LANG_STORE.FR.SettingsOption.AccountWideEnabled = LANG_STORE.EN.SettingsOption.AccountWideEnabled
LANG_STORE.FR.SettingsOption.AccountWideEnabledTooltip = LANG_STORE.EN.SettingsOption.AccountWideEnabledTooltip
LANG_STORE.FR.SettingsOption.ShowEveryUpdate = "Affichage de chaque mise à jour" LANG_STORE.FR.SettingsOption.ShowEveryUpdate = "Affichage de chaque mise à jour"
LANG_STORE.FR.SettingsOption.ShowEveryUpdateTooltip = "Affiche un message pour chaque mise à jour d'un succès. Le reste du temps les messages n'apparaissent que sous forme de plage de x%" LANG_STORE.FR.SettingsOption.ShowEveryUpdateTooltip = "Affiche un message pour chaque mise à jour d'un succès. Le reste du temps les messages n'apparaissent que sous forme de plage de x%"

View File

@ -5,15 +5,6 @@
-- Function to determine if Account Wide Settings should be used
function AchievementInfo.loadUseAccountWideSettings()
return ZO_SavedVars:New("ACHIEVEMENT_INFO_DB_USE_AW", 1, nil, {
enabled = false
})
end
-- Function to set and load the Saved Variables -- Function to set and load the Saved Variables
function AchievementInfo.loadSavedVars() function AchievementInfo.loadSavedVars()
local defaults = { local defaults = {
@ -45,14 +36,9 @@ function AchievementInfo.loadSavedVars()
cat20 = true, cat20 = true,
cat21 = true, cat21 = true,
cat22 = true, cat22 = true,
-- ... new one default to true
devDebug = false devDebug = false
} }
if AchievementInfo.useAccountWideSettings["enabled"] == true then
return ZO_SavedVars:NewAccountWide("ACHIEVEMENT_INFO_DB", 1, nil, defaults)
end
return ZO_SavedVars:New("ACHIEVEMENT_INFO_DB", 1, nil, defaults) return ZO_SavedVars:New("ACHIEVEMENT_INFO_DB", 1, nil, defaults)
end end
@ -63,16 +49,16 @@ function AchievementInfo.createSettingsPanel()
local panelData = { local panelData = {
type = "panel", type = "panel",
name = AchievementInfo.name, name = AchievementInfo.name,
displayName = AchievementInfo.clrDefault .. AchievementInfo.name, displayName = AchievementInfo.clrDefault..AchievementInfo.name,
author = AchievementInfo.author, author = AchievementInfo.author,
version = string.format("%.2f", AchievementInfo.version), version = string.format("%.1f", AchievementInfo.version),
slashCommand = "/achievementInfo" slashCommand = "/achievementInfo"
} }
local optionsTable = { local optionsTable = {
[1] = { [1] = {
type = "header", type = "header",
name = AchievementInfo.clrSettingsHeader .. LANG.SettingsHeader.General name = AchievementInfo.clrSettingsHeader..LANG.SettingsHeader.General
}, },
[2] = { [2] = {
type = "checkbox", type = "checkbox",
@ -83,21 +69,13 @@ function AchievementInfo.createSettingsPanel()
warning = LANG.SettingsOption.AddOnEnabledWarning warning = LANG.SettingsOption.AddOnEnabledWarning
}, },
[3] = { [3] = {
type = "checkbox",
name = LANG.SettingsOption.AccountWideEnabled,
tooltip = LANG.SettingsOption.AccountWideEnabledTooltip,
getFunc = function() return AchievementInfo.useAccountWideSettings["enabled"] end,
setFunc = function() AchievementInfo.toggleAccountWideSettings() end,
requiresReload = true
},
[4] = {
type = "checkbox", type = "checkbox",
name = LANG.SettingsOption.ShowEveryUpdate, name = LANG.SettingsOption.ShowEveryUpdate,
tooltip = LANG.SettingsOption.ShowEveryUpdateTooltip, tooltip = LANG.SettingsOption.ShowEveryUpdateTooltip,
getFunc = function() return AchievementInfo.settingGet("genShowEveryUpdate") end, getFunc = function() return AchievementInfo.settingGet("genShowEveryUpdate") end,
setFunc = function() AchievementInfo.settingToogle("genShowEveryUpdate") end setFunc = function() AchievementInfo.settingToogle("genShowEveryUpdate") end
}, },
[5] = { [4] = {
type = "slider", type = "slider",
name = LANG.SettingsOption.ShowUpdateSteps, name = LANG.SettingsOption.ShowUpdateSteps,
tooltip = LANG.SettingsOption.ShowUpdateStepsTooltip, tooltip = LANG.SettingsOption.ShowUpdateStepsTooltip,
@ -108,21 +86,21 @@ function AchievementInfo.createSettingsPanel()
setFunc = function(value) AchievementInfo.settingSet("genShowUpdateSteps", value) end, setFunc = function(value) AchievementInfo.settingSet("genShowUpdateSteps", value) end,
default = 25 default = 25
}, },
[6] = { [5] = {
type = "checkbox", type = "checkbox",
name = LANG.SettingsOption.ShowDetails, name = LANG.SettingsOption.ShowDetails,
tooltip = LANG.SettingsOption.ShowDetailsTooltip, tooltip = LANG.SettingsOption.ShowDetailsTooltip,
getFunc = function() return AchievementInfo.settingGet("genShowDetails") end, getFunc = function() return AchievementInfo.settingGet("genShowDetails") end,
setFunc = function() AchievementInfo.settingToogle("genShowDetails") end setFunc = function() AchievementInfo.settingToogle("genShowDetails") end
}, },
[7] = { [6] = {
type = "checkbox", type = "checkbox",
name = LANG.SettingsOption.ShowOpenDetailsOnly, name = LANG.SettingsOption.ShowOpenDetailsOnly,
tooltip = LANG.SettingsOption.ShowOpenDetailsOnlyTooltip, tooltip = LANG.SettingsOption.ShowOpenDetailsOnlyTooltip,
getFunc = function() return AchievementInfo.settingGet("genShowOpenDetailsOnly") end, getFunc = function() return AchievementInfo.settingGet("genShowOpenDetailsOnly") end,
setFunc = function() AchievementInfo.settingToogle("genShowOpenDetailsOnly") end setFunc = function() AchievementInfo.settingToogle("genShowOpenDetailsOnly") end
}, },
[8] = { [7] = {
type = "checkbox", type = "checkbox",
name = LANG.SettingsOption.OneElementPerLine, name = LANG.SettingsOption.OneElementPerLine,
tooltip = LANG.SettingsOption.OneElementPerLineTooltip, tooltip = LANG.SettingsOption.OneElementPerLineTooltip,
@ -130,11 +108,11 @@ function AchievementInfo.createSettingsPanel()
setFunc = function() AchievementInfo.settingToogle("genOnePerLine") end, setFunc = function() AchievementInfo.settingToogle("genOnePerLine") end,
warning = LANG.SettingsOption.OneElementPerLineWarning warning = LANG.SettingsOption.OneElementPerLineWarning
}, },
[9] = { [8] = {
type = "header", type = "header",
name = AchievementInfo.clrSettingsHeader .. LANG.SettingsHeader.Categories name = AchievementInfo.clrSettingsHeader .. LANG.SettingsHeader.Categories
}, },
[10] = { [9] = {
type = "description", type = "description",
text = LANG.SettingsHeader.CategoriesDescription .. ":" text = LANG.SettingsHeader.CategoriesDescription .. ":"
} }
@ -150,8 +128,8 @@ function AchievementInfo.createSettingsPanel()
type = "checkbox", type = "checkbox",
name = catName, name = catName,
tooltip = LANG.SettingsOption.CategoryTooltip .. " '" .. catName .. "'", tooltip = LANG.SettingsOption.CategoryTooltip .. " '" .. catName .. "'",
getFunc = function() return AchievementInfo.settingGetForCategory("cat" .. i) end, getFunc = function() return AchievementInfo.settingGet("cat"..i) end,
setFunc = function() AchievementInfo.settingToogle("cat" .. i) end setFunc = function() AchievementInfo.settingToogle("cat"..i) end
}) })
end end
@ -171,8 +149,8 @@ function AchievementInfo.createSettingsPanel()
}) })
-- Register -- Register
LibAddonMenu2:RegisterAddonPanel(AchievementInfo.name .. "SettingsPanel", panelData) LibAddonMenu2:RegisterAddonPanel(AchievementInfo.name.."SettingsPanel", panelData)
LibAddonMenu2:RegisterOptionControls(AchievementInfo.name .. "SettingsPanel", optionsTable) LibAddonMenu2:RegisterOptionControls(AchievementInfo.name.."SettingsPanel", optionsTable)
end end
@ -189,18 +167,6 @@ end
-- Function to retrieve settings for categories (default true)
function AchievementInfo.settingGetForCategory(id)
if AchievementInfo.savedVars[id] == nil then
AchievementInfo.savedVars[id] = true
return true
else
return AchievementInfo.savedVars[id]
end
end
-- Function to toggle Checkbox values -- Function to toggle Checkbox values
function AchievementInfo.settingToogle(id) function AchievementInfo.settingToogle(id)
if AchievementInfo.savedVars[id] == false then if AchievementInfo.savedVars[id] == false then
@ -212,17 +178,6 @@ end
-- Function to toggle Checkbox value for accountWideSettings
function AchievementInfo.toggleAccountWideSettings()
if AchievementInfo.useAccountWideSettings["enabled"] == false then
AchievementInfo.useAccountWideSettings["enabled"] = true
else
AchievementInfo.useAccountWideSettings["enabled"] = false
end
end
-- Function to set settings -- Function to set settings
function AchievementInfo.settingSet(id, value) function AchievementInfo.settingSet(id, value)
AchievementInfo.savedVars[id] = value AchievementInfo.savedVars[id] = value

View File

@ -1,21 +1,5 @@
#### Notable Changes #### Notable Changes
##### Release 4.15
* Fixed "bracket style" of the achievement links, thanks to DakJaniels
##### Release 4.5
* Fixed "ShowDetails" option working only in combination with "ShowOpenDetailsOnly"
##### Release 4.3
* Fixed an error with gendered achievement descriptions
##### Release 4.0
* Added accountwide settings
* Added an "use accountwide settings" option to the settings of each character
##### Release 3.0
* Removed the bundled Dependency LibAddonMenu-2.0: You have to download it on your own now
##### Release 2.24 ##### Release 2.24
* Updated Dependencies * Updated Dependencies
* Removed LibStub Usage * Removed LibStub Usage

34
Libs/LibAddonMenu-2.0.txt Normal file
View File

@ -0,0 +1,34 @@
## APIVersion: 100029 100030
## Title: LibAddonMenu-2.0
## Version: 2.0 r30
## AddOnVersion: 30
## IsLibrary: true
## OptionalDependsOn: LibStub LibDebugLogger
## Author: Seerah, sirinsidiator, et al.
## Contributors: votan, merlight, Garkin, Randactyl, KuroiLight, silvereyes333, Baertram, kyoma, klingo, phuein
## Description: A library to aid in the creation of option panels.
##
## This Add-on is not created by, affiliated with or sponsored by ZeniMax Media Inc. or its affiliates.
## The Elder Scrolls® and related logos are registered trademarks or trademarks of ZeniMax Media Inc. in the United States and/or other countries.
## All rights reserved
##
## You can read the full terms at https://account.elderscrollsonline.com/add-on-terms
LibStub\LibStub.lua
LibAddonMenu-2.0\LibAddonMenu-2.0.lua
LibAddonMenu-2.0\controls\panel.lua
LibAddonMenu-2.0\controls\submenu.lua
LibAddonMenu-2.0\controls\button.lua
LibAddonMenu-2.0\controls\checkbox.lua
LibAddonMenu-2.0\controls\colorpicker.lua
LibAddonMenu-2.0\controls\custom.lua
LibAddonMenu-2.0\controls\description.lua
LibAddonMenu-2.0\controls\dropdown.lua
LibAddonMenu-2.0\controls\editbox.lua
LibAddonMenu-2.0\controls\header.lua
LibAddonMenu-2.0\controls\slider.lua
LibAddonMenu-2.0\controls\texture.lua
LibAddonMenu-2.0\controls\iconpicker.lua
LibAddonMenu-2.0\controls\divider.lua

View File

@ -0,0 +1,201 @@
The Artistic License 2.0
Copyright (c) 2016 Ryan Lakanen (Seerah)
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
This license establishes the terms under which a given free software
Package may be copied, modified, distributed, and/or redistributed.
The intent is that the Copyright Holder maintains some artistic
control over the development of that Package while still keeping the
Package available as open source and free software.
You are always permitted to make arrangements wholly outside of this
license directly with the Copyright Holder of a given Package. If the
terms of this license do not permit the full use that you propose to
make of the Package, you should contact the Copyright Holder and seek
a different licensing arrangement.
Definitions
"Copyright Holder" means the individual(s) or organization(s)
named in the copyright notice for the entire Package.
"Contributor" means any party that has contributed code or other
material to the Package, in accordance with the Copyright Holder's
procedures.
"You" and "your" means any person who would like to copy,
distribute, or modify the Package.
"Package" means the collection of files distributed by the
Copyright Holder, and derivatives of that collection and/or of
those files. A given Package may consist of either the Standard
Version, or a Modified Version.
"Distribute" means providing a copy of the Package or making it
accessible to anyone else, or in the case of a company or
organization, to others outside of your company or organization.
"Distributor Fee" means any fee that you charge for Distributing
this Package or providing support for this Package to another
party. It does not mean licensing fees.
"Standard Version" refers to the Package if it has not been
modified, or has been modified only in ways explicitly requested
by the Copyright Holder.
"Modified Version" means the Package, if it has been changed, and
such changes were not explicitly requested by the Copyright
Holder.
"Original License" means this Artistic License as Distributed with
the Standard Version of the Package, in its current version or as
it may be modified by The Perl Foundation in the future.
"Source" form means the source code, documentation source, and
configuration files for the Package.
"Compiled" form means the compiled bytecode, object code, binary,
or any other form resulting from mechanical transformation or
translation of the Source form.
Permission for Use and Modification Without Distribution
(1) You are permitted to use the Standard Version and create and use
Modified Versions for any purpose without restriction, provided that
you do not Distribute the Modified Version.
Permissions for Redistribution of the Standard Version
(2) You may Distribute verbatim copies of the Source form of the
Standard Version of this Package in any medium without restriction,
either gratis or for a Distributor Fee, provided that you duplicate
all of the original copyright notices and associated disclaimers. At
your discretion, such verbatim copies may or may not include a
Compiled form of the Package.
(3) You may apply any bug fixes, portability changes, and other
modifications made available from the Copyright Holder. The resulting
Package will still be considered the Standard Version, and as such
will be subject to the Original License.
Distribution of Modified Versions of the Package as Source
(4) You may Distribute your Modified Version as Source (either gratis
or for a Distributor Fee, and with or without a Compiled form of the
Modified Version) provided that you clearly document how it differs
from the Standard Version, including, but not limited to, documenting
any non-standard features, executables, or modules, and provided that
you do at least ONE of the following:
(a) make the Modified Version available to the Copyright Holder
of the Standard Version, under the Original License, so that the
Copyright Holder may include your modifications in the Standard
Version.
(b) ensure that installation of your Modified Version does not
prevent the user installing or running the Standard Version. In
addition, the Modified Version must bear a name that is different
from the name of the Standard Version.
(c) allow anyone who receives a copy of the Modified Version to
make the Source form of the Modified Version available to others
under
(i) the Original License or
(ii) a license that permits the licensee to freely copy,
modify and redistribute the Modified Version using the same
licensing terms that apply to the copy that the licensee
received, and requires that the Source form of the Modified
Version, and of any works derived from it, be made freely
available in that license fees are prohibited but Distributor
Fees are allowed.
Distribution of Compiled Forms of the Standard Version
or Modified Versions without the Source
(5) You may Distribute Compiled forms of the Standard Version without
the Source, provided that you include complete instructions on how to
get the Source of the Standard Version. Such instructions must be
valid at the time of your distribution. If these instructions, at any
time while you are carrying out such distribution, become invalid, you
must provide new instructions on demand or cease further distribution.
If you provide valid instructions or cease distribution within thirty
days after you become aware that the instructions are invalid, then
you do not forfeit any of your rights under this license.
(6) You may Distribute a Modified Version in Compiled form without
the Source, provided that you comply with Section 4 with respect to
the Source of the Modified Version.
Aggregating or Linking the Package
(7) You may aggregate the Package (either the Standard Version or
Modified Version) with other packages and Distribute the resulting
aggregation provided that you do not charge a licensing fee for the
Package. Distributor Fees are permitted, and licensing fees for other
components in the aggregation are permitted. The terms of this license
apply to the use and Distribution of the Standard or Modified Versions
as included in the aggregation.
(8) You are permitted to link Modified and Standard Versions with
other works, to embed the Package in a larger work of your own, or to
build stand-alone binary or bytecode versions of applications that
include the Package, and Distribute the result without restriction,
provided the result does not expose a direct interface to the Package.
Items That are Not Considered Part of a Modified Version
(9) Works (including, but not limited to, modules and scripts) that
merely extend or make use of the Package, do not, by themselves, cause
the Package to be a Modified Version. In addition, such works are not
considered parts of the Package itself, and are not subject to the
terms of this license.
General Provisions
(10) Any use, modification, and distribution of the Standard or
Modified Versions is governed by this Artistic License. By using,
modifying or distributing the Package, you accept this license. Do not
use, modify, or distribute the Package, if you do not accept this
license.
(11) If your Modified Version has been derived from a Modified
Version made by someone other than you, you are nevertheless required
to ensure that your Modified Version complies with the requirements of
this license.
(12) This license does not grant you the right to use any trademark,
service mark, tradename, or logo of the Copyright Holder.
(13) This license includes the non-exclusive, worldwide,
free-of-charge patent license to make, have made, use, offer to sell,
sell, import and otherwise transfer the Package with respect to any
patent claims licensable by the Copyright Holder that are necessarily
infringed by the Package. If you institute patent litigation
(including a cross-claim or counterclaim) against any party alleging
that the Package constitutes direct or contributory patent
infringement, then this Artistic License to you shall terminate on the
date that such litigation is filed.
(14) Disclaimer of Warranty:
THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS
IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL
LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,91 @@
--[[buttonData = {
type = "button",
name = "My Button", -- string id or function returning a string
func = function() end,
tooltip = "Button's tooltip text.", -- string id or function returning a string (optional)
width = "full", -- or "half" (optional)
disabled = function() return db.someBooleanSetting end, -- or boolean (optional)
icon = "icon\\path.dds", -- (optional)
isDangerous = false, -- boolean, if set to true, the button text will be red and a confirmation dialog with the button label and warning text will show on click before the callback is executed (optional)
warning = "Will need to reload the UI.", -- (optional)
reference = "MyAddonButton", -- unique global reference to control (optional)
} ]]
local widgetVersion = 11
local LAM = LibStub("LibAddonMenu-2.0")
if not LAM:RegisterWidget("button", widgetVersion) then return end
local wm = WINDOW_MANAGER
local function UpdateDisabled(control)
local disable = control.data.disabled
if type(disable) == "function" then
disable = disable()
end
control.button:SetEnabled(not disable)
end
--controlName is optional
local MIN_HEIGHT = 28 -- default_button height
local HALF_WIDTH_LINE_SPACING = 2
function LAMCreateControl.button(parent, buttonData, controlName)
local control = LAM.util.CreateBaseControl(parent, buttonData, controlName)
control:SetMouseEnabled(true)
local width = control:GetWidth()
if control.isHalfWidth then
control:SetDimensions(width / 2, MIN_HEIGHT * 2 + HALF_WIDTH_LINE_SPACING)
else
control:SetDimensions(width, MIN_HEIGHT)
end
if buttonData.icon then
control.button = wm:CreateControl(nil, control, CT_BUTTON)
control.button:SetDimensions(26, 26)
control.button:SetNormalTexture(buttonData.icon)
control.button:SetPressedOffset(2, 2)
else
--control.button = wm:CreateControlFromVirtual(controlName.."Button", control, "ZO_DefaultButton")
control.button = wm:CreateControlFromVirtual(nil, control, "ZO_DefaultButton")
control.button:SetWidth(width / 3)
control.button:SetText(LAM.util.GetStringFromValue(buttonData.name))
if buttonData.isDangerous then control.button:SetNormalFontColor(ZO_ERROR_COLOR:UnpackRGBA()) end
end
local button = control.button
button:SetAnchor(control.isHalfWidth and CENTER or RIGHT)
button:SetClickSound("Click")
button.data = {tooltipText = LAM.util.GetStringFromValue(buttonData.tooltip)}
button:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter)
button:SetHandler("OnMouseExit", ZO_Options_OnMouseExit)
button:SetHandler("OnClicked", function(...)
local args = {...}
local function callback()
buttonData.func(unpack(args))
LAM.util.RequestRefreshIfNeeded(control)
end
if(buttonData.isDangerous) then
local title = LAM.util.GetStringFromValue(buttonData.name)
local body = LAM.util.GetStringFromValue(buttonData.warning)
LAM.util.ShowConfirmationDialog(title, body, callback)
else
callback()
end
end)
if buttonData.warning ~= nil then
control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon")
control.warning:SetAnchor(RIGHT, button, LEFT, -5, 0)
control.UpdateWarning = LAM.util.UpdateWarning
control:UpdateWarning()
end
if buttonData.disabled ~= nil then
control.UpdateDisabled = UpdateDisabled
control:UpdateDisabled()
end
LAM.util.RegisterForRefreshIfNeeded(control)
return control
end

View File

@ -0,0 +1,142 @@
--[[checkboxData = {
type = "checkbox",
name = "My Checkbox", -- or string id or function returning a string
getFunc = function() return db.var end,
setFunc = function(value) db.var = value doStuff() end,
tooltip = "Checkbox's tooltip text.", -- or string id or function returning a string (optional)
width = "full", -- or "half" (optional)
disabled = function() return db.someBooleanSetting end, -- or boolean (optional)
warning = "May cause permanent awesomeness.", -- or string id or function returning a string (optional)
requiresReload = false, -- boolean, if set to true, the warning text will contain a notice that changes are only applied after an UI reload and any change to the value will make the "Apply Settings" button appear on the panel which will reload the UI when pressed (optional)
default = defaults.var, -- a boolean or function that returns a boolean (optional)
reference = "MyAddonCheckbox", -- unique global reference to control (optional)
} ]]
local widgetVersion = 14
local LAM = LibStub("LibAddonMenu-2.0")
if not LAM:RegisterWidget("checkbox", widgetVersion) then return end
local wm = WINDOW_MANAGER
--label
local enabledColor = ZO_DEFAULT_ENABLED_COLOR
local enabledHLcolor = ZO_HIGHLIGHT_TEXT
local disabledColor = ZO_DEFAULT_DISABLED_COLOR
local disabledHLcolor = ZO_DEFAULT_DISABLED_MOUSEOVER_COLOR
--checkbox
local checkboxColor = ZO_NORMAL_TEXT
local checkboxHLcolor = ZO_HIGHLIGHT_TEXT
local function UpdateDisabled(control)
local disable
if type(control.data.disabled) == "function" then
disable = control.data.disabled()
else
disable = control.data.disabled
end
control.label:SetColor((disable and ZO_DEFAULT_DISABLED_COLOR or control.value and ZO_DEFAULT_ENABLED_COLOR or ZO_DEFAULT_DISABLED_COLOR):UnpackRGBA())
control.checkbox:SetColor((disable and ZO_DEFAULT_DISABLED_COLOR or ZO_NORMAL_TEXT):UnpackRGBA())
--control:SetMouseEnabled(not disable)
--control:SetMouseEnabled(true)
control.isDisabled = disable
end
local function ToggleCheckbox(control)
if control.value then
control.label:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA())
control.checkbox:SetText(control.checkedText)
else
control.label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA())
control.checkbox:SetText(control.uncheckedText)
end
end
local function UpdateValue(control, forceDefault, value)
if forceDefault then --if we are forcing defaults
value = LAM.util.GetDefaultValue(control.data.default)
control.data.setFunc(value)
elseif value ~= nil then --our value could be false
control.data.setFunc(value)
--after setting this value, let's refresh the others to see if any should be disabled or have their settings changed
LAM.util.RequestRefreshIfNeeded(control)
else
value = control.data.getFunc()
end
control.value = value
ToggleCheckbox(control)
end
local function OnMouseEnter(control)
ZO_Options_OnMouseEnter(control)
if control.isDisabled then return end
local label = control.label
if control.value then
label:SetColor(ZO_HIGHLIGHT_TEXT:UnpackRGBA())
else
label:SetColor(ZO_DEFAULT_DISABLED_MOUSEOVER_COLOR:UnpackRGBA())
end
control.checkbox:SetColor(ZO_HIGHLIGHT_TEXT:UnpackRGBA())
end
local function OnMouseExit(control)
ZO_Options_OnMouseExit(control)
if control.isDisabled then return end
local label = control.label
if control.value then
label:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA())
else
label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA())
end
control.checkbox:SetColor(ZO_NORMAL_TEXT:UnpackRGBA())
end
--controlName is optional
function LAMCreateControl.checkbox(parent, checkboxData, controlName)
local control = LAM.util.CreateLabelAndContainerControl(parent, checkboxData, controlName)
control:SetHandler("OnMouseEnter", OnMouseEnter)
control:SetHandler("OnMouseExit", OnMouseExit)
control:SetHandler("OnMouseUp", function(control)
if control.isDisabled then return end
PlaySound(SOUNDS.DEFAULT_CLICK)
control.value = not control.value
control:UpdateValue(false, control.value)
end)
control.checkbox = wm:CreateControl(nil, control.container, CT_LABEL)
local checkbox = control.checkbox
checkbox:SetAnchor(LEFT, control.container, LEFT, 0, 0)
checkbox:SetFont("ZoFontGameBold")
checkbox:SetColor(ZO_NORMAL_TEXT:UnpackRGBA())
control.checkedText = GetString(SI_CHECK_BUTTON_ON):upper()
control.uncheckedText = GetString(SI_CHECK_BUTTON_OFF):upper()
if checkboxData.warning ~= nil or checkboxData.requiresReload then
control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon")
control.warning:SetAnchor(RIGHT, checkbox, LEFT, -5, 0)
control.UpdateWarning = LAM.util.UpdateWarning
control:UpdateWarning()
end
control.data.tooltipText = LAM.util.GetStringFromValue(checkboxData.tooltip)
control.UpdateValue = UpdateValue
control:UpdateValue()
if checkboxData.disabled ~= nil then
control.UpdateDisabled = UpdateDisabled
control:UpdateDisabled()
end
LAM.util.RegisterForRefreshIfNeeded(control)
LAM.util.RegisterForReloadIfNeeded(control)
return control
end

View File

@ -0,0 +1,110 @@
--[[colorpickerData = {
type = "colorpicker",
name = "My Color Picker", -- or string id or function returning a string
getFunc = function() return db.r, db.g, db.b, db.a end, -- (alpha is optional)
setFunc = function(r,g,b,a) db.r=r, db.g=g, db.b=b, db.a=a end, -- (alpha is optional)
tooltip = "Color Picker's tooltip text.", -- or string id or function returning a string (optional)
width = "full", -- or "half" (optional)
disabled = function() return db.someBooleanSetting end, -- or boolean (optional)
warning = "May cause permanent awesomeness.", -- or string id or function returning a string (optional)
requiresReload = false, -- boolean, if set to true, the warning text will contain a notice that changes are only applied after an UI reload and any change to the value will make the "Apply Settings" button appear on the panel which will reload the UI when pressed (optional)
default = {r = defaults.r, g = defaults.g, b = defaults.b, a = defaults.a}, -- (optional) table of default color values (or default = defaultColor, where defaultColor is a table with keys of r, g, b[, a]) or a function that returns the color
reference = "MyAddonColorpicker" -- unique global reference to control (optional)
} ]]
local widgetVersion = 14
local LAM = LibStub("LibAddonMenu-2.0")
if not LAM:RegisterWidget("colorpicker", widgetVersion) then return end
local wm = WINDOW_MANAGER
local function UpdateDisabled(control)
local disable
if type(control.data.disabled) == "function" then
disable = control.data.disabled()
else
disable = control.data.disabled
end
if disable then
control.label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA())
else
control.label:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA())
end
control.isDisabled = disable
end
local function UpdateValue(control, forceDefault, valueR, valueG, valueB, valueA)
if forceDefault then --if we are forcing defaults
local color = LAM.util.GetDefaultValue(control.data.default)
valueR, valueG, valueB, valueA = color.r, color.g, color.b, color.a
control.data.setFunc(valueR, valueG, valueB, valueA)
elseif valueR and valueG and valueB then
control.data.setFunc(valueR, valueG, valueB, valueA or 1)
--after setting this value, let's refresh the others to see if any should be disabled or have their settings changed
LAM.util.RequestRefreshIfNeeded(control)
else
valueR, valueG, valueB, valueA = control.data.getFunc()
end
control.thumb:SetColor(valueR, valueG, valueB, valueA or 1)
end
function LAMCreateControl.colorpicker(parent, colorpickerData, controlName)
local control = LAM.util.CreateLabelAndContainerControl(parent, colorpickerData, controlName)
control.color = control.container
local color = control.color
control.thumb = wm:CreateControl(nil, color, CT_TEXTURE)
local thumb = control.thumb
thumb:SetDimensions(36, 18)
thumb:SetAnchor(LEFT, color, LEFT, 4, 0)
color.border = wm:CreateControl(nil, color, CT_TEXTURE)
local border = color.border
border:SetTexture("EsoUI\\Art\\ChatWindow\\chatOptions_bgColSwatch_frame.dds")
border:SetTextureCoords(0, .625, 0, .8125)
border:SetDimensions(40, 22)
border:SetAnchor(CENTER, thumb, CENTER, 0, 0)
local function ColorPickerCallback(r, g, b, a)
control:UpdateValue(false, r, g, b, a)
end
control:SetHandler("OnMouseUp", function(self, btn, upInside)
if self.isDisabled then return end
if upInside then
local r, g, b, a = colorpickerData.getFunc()
if IsInGamepadPreferredMode() then
COLOR_PICKER_GAMEPAD:Show(ColorPickerCallback, r, g, b, a)
else
COLOR_PICKER:Show(ColorPickerCallback, r, g, b, a)
end
end
end)
if colorpickerData.warning ~= nil or colorpickerData.requiresReload then
control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon")
control.warning:SetAnchor(RIGHT, control.color, LEFT, -5, 0)
control.UpdateWarning = LAM.util.UpdateWarning
control:UpdateWarning()
end
control.data.tooltipText = LAM.util.GetStringFromValue(colorpickerData.tooltip)
control.UpdateValue = UpdateValue
control:UpdateValue()
if colorpickerData.disabled ~= nil then
control.UpdateDisabled = UpdateDisabled
control:UpdateDisabled()
end
LAM.util.RegisterForRefreshIfNeeded(control)
LAM.util.RegisterForReloadIfNeeded(control)
return control
end

View File

@ -0,0 +1,35 @@
--[[customData = {
type = "custom",
reference = "MyAddonCustomControl", -- unique name for your control to use as reference (optional)
refreshFunc = function(customControl) end, -- function to call when panel/controls refresh (optional)
width = "full", -- or "half" (optional)
} ]]
local widgetVersion = 7
local LAM = LibStub("LibAddonMenu-2.0")
if not LAM:RegisterWidget("custom", widgetVersion) then return end
local function UpdateValue(control)
if control.data.refreshFunc then
control.data.refreshFunc(control)
end
end
local MIN_HEIGHT = 26
function LAMCreateControl.custom(parent, customData, controlName)
local control = LAM.util.CreateBaseControl(parent, customData, controlName)
local width = control:GetWidth()
control:SetResizeToFitDescendents(true)
if control.isHalfWidth then --note these restrictions
control:SetDimensionConstraints(width / 2, MIN_HEIGHT, width / 2, MIN_HEIGHT * 4)
else
control:SetDimensionConstraints(width, MIN_HEIGHT, width, MIN_HEIGHT * 4)
end
control.UpdateValue = UpdateValue
LAM.util.RegisterForRefreshIfNeeded(control)
return control
end

View File

@ -0,0 +1,96 @@
--[[descriptionData = {
type = "description",
text = "My description text to display.", -- or string id or function returning a string
title = "My Title", -- or string id or function returning a string (optional)
width = "full", -- or "half" (optional)
disabled = function() return db.someBooleanSetting end, -- or boolean (optional)
enableLinks = nil, -- or true for default tooltips, or function OnLinkClicked handler (optional)
-- see: https://wiki.esoui.com/UI_XML#OnLinkClicked
reference = "MyAddonDescription" -- unique global reference to control (optional)
} ]]
local widgetVersion = 10
local LAM = LibStub("LibAddonMenu-2.0")
if not LAM:RegisterWidget("description", widgetVersion) then return end
local wm = WINDOW_MANAGER
local GetDefaultValue = LAM.util.GetDefaultValue
local GetColorForState = LAM.util.GetColorForState
local function OnLinkClicked(control, linkData, linkText, button)
ZO_LinkHandler_OnLinkClicked(linkText, button)
end
local function UpdateDisabled(control)
local disable = GetDefaultValue(control.data.disabled)
if disable ~= control.disabled then
local color = GetColorForState(disable)
control.desc:SetColor(color:UnpackRGBA())
if control.title then
control.title:SetColor(color:UnpackRGBA())
end
control.disabled = disable
end
end
local function UpdateValue(control)
if control.title then
control.title:SetText(LAM.util.GetStringFromValue(control.data.title))
end
control.desc:SetText(LAM.util.GetStringFromValue(control.data.text))
end
function LAMCreateControl.description(parent, descriptionData, controlName)
local control = LAM.util.CreateBaseControl(parent, descriptionData, controlName)
local isHalfWidth = control.isHalfWidth
local width = control:GetWidth()
control:SetResizeToFitDescendents(true)
if isHalfWidth then
control:SetDimensionConstraints(width / 2, 0, width / 2, 0)
else
control:SetDimensionConstraints(width, 0, width, 0)
end
control.desc = wm:CreateControl(nil, control, CT_LABEL)
local desc = control.desc
desc:SetVerticalAlignment(TEXT_ALIGN_TOP)
desc:SetFont("ZoFontGame")
desc:SetText(LAM.util.GetStringFromValue(descriptionData.text))
desc:SetWidth(isHalfWidth and width / 2 or width)
if descriptionData.title then
control.title = wm:CreateControl(nil, control, CT_LABEL)
local title = control.title
title:SetWidth(isHalfWidth and width / 2 or width)
title:SetAnchor(TOPLEFT, control, TOPLEFT)
title:SetFont("ZoFontWinH4")
title:SetText(LAM.util.GetStringFromValue(descriptionData.title))
desc:SetAnchor(TOPLEFT, title, BOTTOMLEFT)
else
desc:SetAnchor(TOPLEFT)
end
if descriptionData.enableLinks then
desc:SetMouseEnabled(true)
desc:SetLinkEnabled(true)
if type(descriptionData.enableLinks) == "function" then
desc:SetHandler("OnLinkClicked", descriptionData.enableLinks)
else
desc:SetHandler("OnLinkClicked", OnLinkClicked)
end
end
control.UpdateValue = UpdateValue
if descriptionData.disabled ~= nil then
control.UpdateDisabled = UpdateDisabled
control:UpdateDisabled()
end
LAM.util.RegisterForRefreshIfNeeded(control)
return control
end

View File

@ -0,0 +1,45 @@
--[[dividerData = {
type = "divider",
width = "full", -- or "half" (optional)
height = 10, -- (optional)
alpha = 0.25, -- (optional)
reference = "MyAddonDivider" -- unique global reference to control (optional)
} ]]
local widgetVersion = 2
local LAM = LibStub("LibAddonMenu-2.0")
if not LAM:RegisterWidget("divider", widgetVersion) then return end
local wm = WINDOW_MANAGER
local MIN_HEIGHT = 10
local MAX_HEIGHT = 50
local MIN_ALPHA = 0
local MAX_ALPHA = 1
local DEFAULT_ALPHA = 0.25
local function GetValueInRange(value, min, max, default)
if not value or type(value) ~= "number" then
return default
end
return math.min(math.max(min, value), max)
end
function LAMCreateControl.divider(parent, dividerData, controlName)
local control = LAM.util.CreateBaseControl(parent, dividerData, controlName)
local isHalfWidth = control.isHalfWidth
local width = control:GetWidth()
local height = GetValueInRange(dividerData.height, MIN_HEIGHT, MAX_HEIGHT, MIN_HEIGHT)
local alpha = GetValueInRange(dividerData.alpha, MIN_ALPHA, MAX_ALPHA, DEFAULT_ALPHA)
control:SetDimensions(isHalfWidth and width / 2 or width, height)
control.divider = wm:CreateControlFromVirtual(nil, control, "ZO_Options_Divider")
local divider = control.divider
divider:SetWidth(isHalfWidth and width / 2 or width)
divider:SetAnchor(TOPLEFT)
divider:SetAlpha(alpha)
return control
end

View File

@ -0,0 +1,432 @@
--[[dropdownData = {
type = "dropdown",
name = "My Dropdown", -- or string id or function returning a string
choices = {"table", "of", "choices"},
choicesValues = {"foo", 2, "three"}, -- if specified, these values will get passed to setFunc instead (optional)
getFunc = function() return db.var end,
setFunc = function(var) db.var = var doStuff() end,
tooltip = "Dropdown's tooltip text.", -- or string id or function returning a string (optional)
choicesTooltips = {"tooltip 1", "tooltip 2", "tooltip 3"}, -- or array of string ids or array of functions returning a string (optional)
sort = "name-up", -- or "name-down", "numeric-up", "numeric-down", "value-up", "value-down", "numericvalue-up", "numericvalue-down" (optional) - if not provided, list will not be sorted
width = "full", -- or "half" (optional)
scrollable = true, -- boolean or number, if set the dropdown will feature a scroll bar if there are a large amount of choices and limit the visible lines to the specified number or 10 if true is used (optional)
disabled = function() return db.someBooleanSetting end, -- or boolean (optional)
warning = "May cause permanent awesomeness.", -- or string id or function returning a string (optional)
requiresReload = false, -- boolean, if set to true, the warning text will contain a notice that changes are only applied after an UI reload and any change to the value will make the "Apply Settings" button appear on the panel which will reload the UI when pressed (optional)
default = defaults.var, -- default value or function that returns the default value (optional)
reference = "MyAddonDropdown" -- unique global reference to control (optional)
} ]]
local widgetVersion = 20
local LAM = LibStub("LibAddonMenu-2.0")
if not LAM:RegisterWidget("dropdown", widgetVersion) then return end
local wm = WINDOW_MANAGER
local cm = CALLBACK_MANAGER
local SORT_BY_VALUE = { ["value"] = {} }
local SORT_BY_VALUE_NUMERIC = { ["value"] = { isNumeric = true } }
local SORT_TYPES = {
name = ZO_SORT_BY_NAME,
numeric = ZO_SORT_BY_NAME_NUMERIC,
value = SORT_BY_VALUE,
numericvalue = SORT_BY_VALUE_NUMERIC,
}
local SORT_ORDERS = {
up = ZO_SORT_ORDER_UP,
down = ZO_SORT_ORDER_DOWN,
}
local function UpdateDisabled(control)
local disable
if type(control.data.disabled) == "function" then
disable = control.data.disabled()
else
disable = control.data.disabled
end
control.dropdown:SetEnabled(not disable)
if disable then
control.label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA())
else
control.label:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA())
end
end
local function UpdateValue(control, forceDefault, value)
if forceDefault then --if we are forcing defaults
value = LAM.util.GetDefaultValue(control.data.default)
control.data.setFunc(value)
control.dropdown:SetSelectedItem(control.choices[value])
elseif value then
control.data.setFunc(value)
--after setting this value, let's refresh the others to see if any should be disabled or have their settings changed
LAM.util.RequestRefreshIfNeeded(control)
else
value = control.data.getFunc()
control.dropdown:SetSelectedItem(control.choices[value])
end
end
local function DropdownCallback(control, choiceText, choice)
choice.control:UpdateValue(false, choice.value or choiceText)
end
local function SetupTooltips(comboBox, choicesTooltips)
local function ShowTooltip(control)
InitializeTooltip(InformationTooltip, control, TOPLEFT, 0, 0, BOTTOMRIGHT)
SetTooltipText(InformationTooltip, LAM.util.GetStringFromValue(control.tooltip))
InformationTooltipTopLevel:BringWindowToTop()
end
local function HideTooltip(control)
ClearTooltip(InformationTooltip)
end
-- allow for tooltips on the drop down entries
local originalShow = comboBox.ShowDropdownInternal
comboBox.ShowDropdownInternal = function(comboBox)
originalShow(comboBox)
local entries = ZO_Menu.items
for i = 1, #entries do
local entry = entries[i]
local control = entries[i].item
control.tooltip = choicesTooltips[i]
entry.onMouseEnter = control:GetHandler("OnMouseEnter")
entry.onMouseExit = control:GetHandler("OnMouseExit")
ZO_PreHookHandler(control, "OnMouseEnter", ShowTooltip)
ZO_PreHookHandler(control, "OnMouseExit", HideTooltip)
end
end
local originalHide = comboBox.HideDropdownInternal
comboBox.HideDropdownInternal = function(self)
local entries = ZO_Menu.items
for i = 1, #entries do
local entry = entries[i]
local control = entries[i].item
control:SetHandler("OnMouseEnter", entry.onMouseEnter)
control:SetHandler("OnMouseExit", entry.onMouseExit)
control.tooltip = nil
end
originalHide(self)
end
end
local function UpdateChoices(control, choices, choicesValues, choicesTooltips)
control.dropdown:ClearItems() --remove previous choices --(need to call :SetSelectedItem()?)
ZO_ClearTable(control.choices)
--build new list of choices
local choices = choices or control.data.choices
local choicesValues = choicesValues or control.data.choicesValues
local choicesTooltips = choicesTooltips or control.data.choicesTooltips
if choicesValues then
assert(#choices == #choicesValues, "choices and choicesValues need to have the same size")
end
if choicesTooltips then
assert(#choices == #choicesTooltips, "choices and choicesTooltips need to have the same size")
if not control.scrollHelper then -- only do this for non-scrollable
SetupTooltips(control.dropdown, choicesTooltips)
end
end
for i = 1, #choices do
local entry = control.dropdown:CreateItemEntry(choices[i], DropdownCallback)
entry.control = control
if choicesValues then
entry.value = choicesValues[i]
end
if choicesTooltips and control.scrollHelper then
entry.tooltip = choicesTooltips[i]
end
control.choices[entry.value or entry.name] = entry.name
control.dropdown:AddItem(entry, not control.data.sort and ZO_COMBOBOX_SUPRESS_UPDATE) --if sort type/order isn't specified, then don't sort
end
end
local function GrabSortingInfo(sortInfo)
local t, i = {}, 1
for info in string.gmatch(sortInfo, "([^%-]+)") do
t[i] = info
i = i + 1
end
return t
end
local ENTRY_ID = 1
local LAST_ENTRY_ID = 2
local OFFSET_X_INDEX = 4
local DEFAULT_VISIBLE_ROWS = 10
local SCROLLABLE_ENTRY_TEMPLATE_HEIGHT = ZO_SCROLLABLE_ENTRY_TEMPLATE_HEIGHT
local SCROLLBAR_PADDING = ZO_SCROLL_BAR_WIDTH
local PADDING_X = GetMenuPadding()
local PADDING_Y = ZO_SCROLLABLE_COMBO_BOX_LIST_PADDING_Y
local LABEL_OFFSET_X = 2
local CONTENT_PADDING = PADDING_X * 4
local ROUNDING_MARGIN = 0.01 -- needed to avoid rare issue with too many anchors processed
local ScrollableDropdownHelper = ZO_Object:Subclass()
function ScrollableDropdownHelper:New(...)
local object = ZO_Object.New(self)
object:Initialize(...)
return object
end
function ScrollableDropdownHelper:Initialize(panel, control, visibleRows)
local combobox = control.combobox
local dropdown = control.dropdown
self.panel = panel
self.control = control
self.combobox = combobox
self.dropdown = dropdown
self.visibleRows = visibleRows
-- clear anchors so we can adjust the width dynamically
dropdown.m_dropdown:ClearAnchors()
dropdown.m_dropdown:SetAnchor(TOPLEFT, combobox, BOTTOMLEFT)
-- handle dropdown or settingsmenu opening/closing
local function onShow() return self:OnShow() end
local function onHide() self:OnHide() end
local function doHide(closedPanel)
if closedPanel == panel then self:DoHide() end
end
ZO_PreHook(dropdown, "ShowDropdownOnMouseUp", onShow)
ZO_PreHook(dropdown, "HideDropdownInternal", onHide)
combobox:SetHandler("OnEffectivelyHidden", onHide)
cm:RegisterCallback("LAM-PanelClosed", doHide)
-- dont fade entries near the edges
local scrollList = dropdown.m_scroll
scrollList.selectionTemplate = nil
scrollList.highlightTemplate = nil
ZO_ScrollList_EnableSelection(scrollList, "ZO_SelectionHighlight")
ZO_ScrollList_EnableHighlight(scrollList, "ZO_SelectionHighlight")
ZO_Scroll_SetUseFadeGradient(scrollList, false)
-- adjust scroll content anchor to mimic menu padding
local scroll = dropdown.m_dropdown:GetNamedChild("Scroll")
local anchor1 = {select(2, scroll:GetAnchor(0))}
local anchor2 = {select(2, scroll:GetAnchor(1))}
anchor1[OFFSET_X_INDEX] = PADDING_X - LABEL_OFFSET_X
anchor2[OFFSET_X_INDEX] = -anchor1[OFFSET_X_INDEX]
scroll:ClearAnchors()
scroll:SetAnchor(unpack(anchor1))
scroll:SetAnchor(unpack(anchor2))
ZO_ScrollList_Commit(scrollList)
-- hook mouse enter/exit
local function onMouseEnter(control) self:OnMouseEnter(control) end
local function onMouseExit(control) self:OnMouseExit(control) end
-- adjust row setup to mimic the highlight padding
local dataType1 = ZO_ScrollList_GetDataTypeTable(dropdown.m_scroll, ENTRY_ID)
local dataType2 = ZO_ScrollList_GetDataTypeTable(dropdown.m_scroll, LAST_ENTRY_ID)
local oSetup = dataType1.setupCallback -- both types have the same setup function
local function SetupEntry(control, data, list)
oSetup(control, data, list)
control.m_label:SetAnchor(LEFT, nil, nil, LABEL_OFFSET_X)
control.m_label:SetAnchor(RIGHT, nil, nil, -LABEL_OFFSET_X)
-- no need to store old ones since we have full ownership of our dropdown controls
if not control.hookedMouseHandlers then --only do it once per control
control.hookedMouseHandlers = true
ZO_PreHookHandler(control, "OnMouseEnter", onMouseEnter)
ZO_PreHookHandler(control, "OnMouseExit", onMouseExit)
end
end
dataType1.setupCallback = SetupEntry
dataType2.setupCallback = SetupEntry
-- adjust dimensions based on entries
local scrollContent = scroll:GetNamedChild("Contents")
dropdown.AddMenuItems = ScrollableDropdownHelper.AddMenuItems
dropdown.AdjustDimensions = function()
local numItems = #dropdown.m_sortedItems
local contentWidth = self:CalculateContentWidth() + CONTENT_PADDING
local anchorOffset = 0
if(numItems > self.visibleRows) then
numItems = self.visibleRows
contentWidth = contentWidth + SCROLLBAR_PADDING
anchorOffset = -SCROLLBAR_PADDING
end
local width = zo_max(contentWidth, dropdown.m_container:GetWidth())
local height = dropdown:GetEntryTemplateHeightWithSpacing() * numItems - dropdown.m_spacing + (PADDING_Y * 2) + ROUNDING_MARGIN
dropdown.m_dropdown:SetWidth(width)
dropdown.m_dropdown:SetHeight(height)
ZO_ScrollList_SetHeight(dropdown.m_scroll, height)
scrollContent:SetAnchor(BOTTOMRIGHT, nil, nil, anchorOffset)
end
end
local function CreateScrollableComboBoxEntry(self, item, index, isLast)
item.m_index = index
item.m_owner = self
local entryType = isLast and LAST_ENTRY_ID or ENTRY_ID
local entry = ZO_ScrollList_CreateDataEntry(entryType, item)
return entry
end
function ScrollableDropdownHelper.AddMenuItems(self) -- self refers to the ZO_ScrollableComboBox here
ZO_ScrollList_Clear(self.m_scroll)
local numItems = #self.m_sortedItems
local dataList = ZO_ScrollList_GetDataList(self.m_scroll)
for i = 1, numItems do
local item = self.m_sortedItems[i]
local entry = CreateScrollableComboBoxEntry(self, item, i, i == numItems)
table.insert(dataList, entry)
end
self:AdjustDimensions()
ZO_ScrollList_Commit(self.m_scroll)
end
function ScrollableDropdownHelper:OnShow()
local dropdown = self.dropdown
-- don't show if there are no entries
if #dropdown.m_sortedItems == 0 then return true end
if dropdown.m_lastParent ~= ZO_Menus then
dropdown.m_lastParent = dropdown.m_dropdown:GetParent()
dropdown.m_dropdown:SetParent(ZO_Menus)
ZO_Menus:BringWindowToTop()
end
end
function ScrollableDropdownHelper:OnHide()
local dropdown = self.dropdown
if dropdown.m_lastParent then
dropdown.m_dropdown:SetParent(dropdown.m_lastParent)
dropdown.m_lastParent = nil
end
end
function ScrollableDropdownHelper:DoHide()
local dropdown = self.dropdown
if dropdown:IsDropdownVisible() then
dropdown:HideDropdown()
end
end
function ScrollableDropdownHelper:CalculateContentWidth()
local dropdown = self.dropdown
local dataType = ZO_ScrollList_GetDataTypeTable(dropdown.m_scroll, 1)
local dummy = dataType.pool:AcquireObject()
dataType.setupCallback(dummy, {
m_owner = dropdown,
name = "Dummy"
}, dropdown)
local maxWidth = 0
local label = dummy.m_label
local entries = dropdown.m_sortedItems
local numItems = #entries
for index = 1, numItems do
label:SetText(entries[index].name)
local width = label:GetTextWidth()
if (width > maxWidth) then
maxWidth = width
end
end
dataType.pool:ReleaseObject(dummy.key)
return maxWidth
end
function ScrollableDropdownHelper:OnMouseEnter(control)
-- call original code if we replace instead of hook the handler
--ZO_ScrollableComboBox_Entry_OnMouseEnter(control)
-- show tooltip
if control.m_data.tooltip then
InitializeTooltip(InformationTooltip, control, TOPLEFT, 0, 0, BOTTOMRIGHT)
SetTooltipText(InformationTooltip, LAM.util.GetStringFromValue(control.m_data.tooltip))
InformationTooltipTopLevel:BringWindowToTop()
end
end
function ScrollableDropdownHelper:OnMouseExit(control)
-- call original code if we replace instead of hook the handler
--ZO_ScrollableComboBox_Entry_OnMouseExit(control)
-- hide tooltip
if control.m_data.tooltip then
ClearTooltip(InformationTooltip)
end
end
function LAMCreateControl.dropdown(parent, dropdownData, controlName)
local control = LAM.util.CreateLabelAndContainerControl(parent, dropdownData, controlName)
control.choices = {}
local countControl = parent
local name = parent:GetName()
if not name or #name == 0 then
countControl = LAMCreateControl
name = "LAM"
end
local comboboxCount = (countControl.comboboxCount or 0) + 1
countControl.comboboxCount = comboboxCount
control.combobox = wm:CreateControlFromVirtual(zo_strjoin(nil, name, "Combobox", comboboxCount), control.container, dropdownData.scrollable and "ZO_ScrollableComboBox" or "ZO_ComboBox")
local combobox = control.combobox
combobox:SetAnchor(TOPLEFT)
combobox:SetDimensions(control.container:GetDimensions())
combobox:SetHandler("OnMouseEnter", function() ZO_Options_OnMouseEnter(control) end)
combobox:SetHandler("OnMouseExit", function() ZO_Options_OnMouseExit(control) end)
control.dropdown = ZO_ComboBox_ObjectFromContainer(combobox)
local dropdown = control.dropdown
dropdown:SetSortsItems(false) -- need to sort ourselves in order to be able to sort by value
if dropdownData.scrollable then
local visibleRows = type(dropdownData.scrollable) == "number" and dropdownData.scrollable or DEFAULT_VISIBLE_ROWS
control.scrollHelper = ScrollableDropdownHelper:New(LAM.util.GetTopPanel(parent), control, visibleRows)
end
ZO_PreHook(dropdown, "UpdateItems", function(self)
assert(not self.m_sortsItems, "built-in dropdown sorting was reactivated, sorting is handled by LAM")
if control.m_sortOrder ~= nil and control.m_sortType then
local sortKey = next(control.m_sortType)
local sortFunc = function(item1, item2) return ZO_TableOrderingFunction(item1, item2, sortKey, control.m_sortType, control.m_sortOrder) end
table.sort(self.m_sortedItems, sortFunc)
end
end)
if dropdownData.sort then
local sortInfo = GrabSortingInfo(dropdownData.sort)
control.m_sortType, control.m_sortOrder = SORT_TYPES[sortInfo[1]], SORT_ORDERS[sortInfo[2]]
elseif dropdownData.choicesValues then
control.m_sortType, control.m_sortOrder = ZO_SORT_ORDER_UP, SORT_BY_VALUE
end
if dropdownData.warning ~= nil or dropdownData.requiresReload then
control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon")
control.warning:SetAnchor(RIGHT, combobox, LEFT, -5, 0)
control.UpdateWarning = LAM.util.UpdateWarning
control:UpdateWarning()
end
control.UpdateChoices = UpdateChoices
control:UpdateChoices(dropdownData.choices, dropdownData.choicesValues)
control.UpdateValue = UpdateValue
control:UpdateValue()
if dropdownData.disabled ~= nil then
control.UpdateDisabled = UpdateDisabled
control:UpdateDisabled()
end
LAM.util.RegisterForRefreshIfNeeded(control)
LAM.util.RegisterForReloadIfNeeded(control)
return control
end

View File

@ -0,0 +1,156 @@
--[[editboxData = {
type = "editbox",
name = "My Editbox", -- or string id or function returning a string
getFunc = function() return db.text end,
setFunc = function(text) db.text = text doStuff() end,
tooltip = "Editbox's tooltip text.", -- or string id or function returning a string (optional)
isMultiline = true, -- boolean (optional)
isExtraWide = true, -- boolean (optional)
width = "full", -- or "half" (optional)
disabled = function() return db.someBooleanSetting end, -- or boolean (optional)
warning = "May cause permanent awesomeness.", -- or string id or function returning a string (optional)
requiresReload = false, -- boolean, if set to true, the warning text will contain a notice that changes are only applied after an UI reload and any change to the value will make the "Apply Settings" button appear on the panel which will reload the UI when pressed (optional)
default = defaults.text, -- default value or function that returns the default value (optional)
reference = "MyAddonEditbox" -- unique global reference to control (optional)
} ]]
local widgetVersion = 14
local LAM = LibStub("LibAddonMenu-2.0")
if not LAM:RegisterWidget("editbox", widgetVersion) then return end
local wm = WINDOW_MANAGER
local function UpdateDisabled(control)
local disable
if type(control.data.disabled) == "function" then
disable = control.data.disabled()
else
disable = control.data.disabled
end
if disable then
control.label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA())
control.editbox:SetColor(ZO_DEFAULT_DISABLED_MOUSEOVER_COLOR:UnpackRGBA())
else
control.label:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA())
control.editbox:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA())
end
--control.editbox:SetEditEnabled(not disable)
control.editbox:SetMouseEnabled(not disable)
end
local function UpdateValue(control, forceDefault, value)
if forceDefault then --if we are forcing defaults
value = LAM.util.GetDefaultValue(control.data.default)
control.data.setFunc(value)
control.editbox:SetText(value)
elseif value then
control.data.setFunc(value)
--after setting this value, let's refresh the others to see if any should be disabled or have their settings changed
LAM.util.RequestRefreshIfNeeded(control)
else
value = control.data.getFunc()
control.editbox:SetText(value)
end
end
local MIN_HEIGHT = 24
local HALF_WIDTH_LINE_SPACING = 2
function LAMCreateControl.editbox(parent, editboxData, controlName)
local control = LAM.util.CreateLabelAndContainerControl(parent, editboxData, controlName)
local container = control.container
control.bg = wm:CreateControlFromVirtual(nil, container, "ZO_EditBackdrop")
local bg = control.bg
bg:SetAnchorFill()
if editboxData.isMultiline then
control.editbox = wm:CreateControlFromVirtual(nil, bg, "ZO_DefaultEditMultiLineForBackdrop")
control.editbox:SetHandler("OnMouseWheel", function(self, delta)
if self:HasFocus() then --only set focus to new spots if the editbox is currently in use
local cursorPos = self:GetCursorPosition()
local text = self:GetText()
local textLen = text:len()
local newPos
if delta > 0 then --scrolling up
local reverseText = text:reverse()
local revCursorPos = textLen - cursorPos
local revPos = reverseText:find("\n", revCursorPos+1)
newPos = revPos and textLen - revPos
else --scrolling down
newPos = text:find("\n", cursorPos+1)
end
if newPos then --if we found a new line, then scroll, otherwise don't
self:SetCursorPosition(newPos)
end
end
end)
else
control.editbox = wm:CreateControlFromVirtual(nil, bg, "ZO_DefaultEditForBackdrop")
end
local editbox = control.editbox
editbox:SetText(editboxData.getFunc())
editbox:SetMaxInputChars(3000)
editbox:SetHandler("OnFocusLost", function(self) control:UpdateValue(false, self:GetText()) end)
editbox:SetHandler("OnEscape", function(self) self:LoseFocus() control:UpdateValue(false, self:GetText()) end)
editbox:SetHandler("OnMouseEnter", function() ZO_Options_OnMouseEnter(control) end)
editbox:SetHandler("OnMouseExit", function() ZO_Options_OnMouseExit(control) end)
local MIN_WIDTH = (parent.GetWidth and (parent:GetWidth() / 10)) or (parent.panel.GetWidth and (parent.panel:GetWidth() / 10)) or 0
control.label:ClearAnchors()
container:ClearAnchors()
control.label:SetAnchor(TOPLEFT, control, TOPLEFT, 0, 0)
container:SetAnchor(BOTTOMRIGHT, control, BOTTOMRIGHT, 0, 0)
if control.isHalfWidth then
container:SetAnchor(BOTTOMRIGHT, control, BOTTOMRIGHT, 0, 0)
end
if editboxData.isExtraWide then
container:SetAnchor(BOTTOMLEFT, control, BOTTOMLEFT, 0, 0)
else
container:SetWidth(MIN_WIDTH * 3.2)
end
if editboxData.isMultiline then
container:SetHeight(MIN_HEIGHT * 3)
else
container:SetHeight(MIN_HEIGHT)
end
if control.isHalfWidth ~= true and editboxData.isExtraWide ~= true then
control:SetHeight(container:GetHeight())
else
control:SetHeight(container:GetHeight() + control.label:GetHeight())
end
editbox:ClearAnchors()
editbox:SetAnchor(TOPLEFT, container, TOPLEFT, 2, 2)
editbox:SetAnchor(BOTTOMRIGHT, container, BOTTOMRIGHT, -2, -2)
if editboxData.warning ~= nil or editboxData.requiresReload then
control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon")
if editboxData.isExtraWide then
control.warning:SetAnchor(BOTTOMRIGHT, control.bg, TOPRIGHT, 2, 0)
else
control.warning:SetAnchor(TOPRIGHT, control.bg, TOPLEFT, -5, 0)
end
control.UpdateWarning = LAM.util.UpdateWarning
control:UpdateWarning()
end
control.UpdateValue = UpdateValue
control:UpdateValue()
if editboxData.disabled ~= nil then
control.UpdateDisabled = UpdateDisabled
control:UpdateDisabled()
end
LAM.util.RegisterForRefreshIfNeeded(control)
LAM.util.RegisterForReloadIfNeeded(control)
return control
end

View File

@ -0,0 +1,42 @@
--[[headerData = {
type = "header",
name = "My Header", -- or string id or function returning a string
width = "full", -- or "half" (optional)
reference = "MyAddonHeader" -- unique global reference to control (optional)
} ]]
local widgetVersion = 8
local LAM = LibStub("LibAddonMenu-2.0")
if not LAM:RegisterWidget("header", widgetVersion) then return end
local wm = WINDOW_MANAGER
local function UpdateValue(control)
control.header:SetText(LAM.util.GetStringFromValue(control.data.name))
end
local MIN_HEIGHT = 30
function LAMCreateControl.header(parent, headerData, controlName)
local control = LAM.util.CreateBaseControl(parent, headerData, controlName)
local isHalfWidth = control.isHalfWidth
local width = control:GetWidth()
control:SetDimensions(isHalfWidth and width / 2 or width, MIN_HEIGHT)
control.divider = wm:CreateControlFromVirtual(nil, control, "ZO_Options_Divider")
local divider = control.divider
divider:SetWidth(isHalfWidth and width / 2 or width)
divider:SetAnchor(TOPLEFT)
control.header = wm:CreateControlFromVirtual(nil, control, "ZO_Options_SectionTitleLabel")
local header = control.header
header:SetAnchor(TOPLEFT, divider, BOTTOMLEFT)
header:SetAnchor(BOTTOMRIGHT)
header:SetText(LAM.util.GetStringFromValue(headerData.name))
control.UpdateValue = UpdateValue
LAM.util.RegisterForRefreshIfNeeded(control)
return control
end

View File

@ -0,0 +1,436 @@
--[[iconpickerData = {
type = "iconpicker",
name = "My Icon Picker", -- or string id or function returning a string
choices = {"texture path 1", "texture path 2", "texture path 3"},
getFunc = function() return db.var end,
setFunc = function(var) db.var = var doStuff() end,
tooltip = "Color Picker's tooltip text.", -- or string id or function returning a string (optional)
choicesTooltips = {"icon tooltip 1", "icon tooltip 2", "icon tooltip 3"}, -- or array of string ids or array of functions returning a string (optional)
maxColumns = 5, -- number of icons in one row (optional)
visibleRows = 4.5, -- number of visible rows (optional)
iconSize = 28, -- size of the icons (optional)
defaultColor = ZO_ColorDef:New("FFFFFF"), -- default color of the icons (optional)
width = "full", --or "half" (optional)
beforeShow = function(control, iconPicker) return preventShow end, -- (optional)
disabled = function() return db.someBooleanSetting end, -- or boolean (optional)
warning = "May cause permanent awesomeness.", -- or string id or function returning a string (optional)
requiresReload = false, -- boolean, if set to true, the warning text will contain a notice that changes are only applied after an UI reload and any change to the value will make the "Apply Settings" button appear on the panel which will reload the UI when pressed (optional)
default = defaults.var, -- default value or function that returns the default value (optional)
reference = "MyAddonIconPicker" -- unique global reference to control (optional)
} ]]
local widgetVersion = 8
local LAM = LibStub("LibAddonMenu-2.0")
if not LAM:RegisterWidget("iconpicker", widgetVersion) then return end
local wm = WINDOW_MANAGER
local IconPickerMenu = ZO_Object:Subclass()
local iconPicker
LAM.util.GetIconPickerMenu = function()
if not iconPicker then
iconPicker = IconPickerMenu:New("LAMIconPicker")
local sceneFragment = LAM:GetAddonSettingsFragment()
ZO_PreHook(sceneFragment, "OnHidden", function()
if not iconPicker.control:IsHidden() then
iconPicker:Clear()
end
end)
end
return iconPicker
end
function IconPickerMenu:New(...)
local object = ZO_Object.New(self)
object:Initialize(...)
return object
end
function IconPickerMenu:Initialize(name)
local control = wm:CreateTopLevelWindow(name)
control:SetDrawTier(DT_HIGH)
control:SetHidden(true)
self.control = control
local scrollContainer = wm:CreateControlFromVirtual(name .. "ScrollContainer", control, "ZO_ScrollContainer")
-- control:SetDimensions(control.container:GetWidth(), height) -- adjust to icon size / col count
scrollContainer:SetAnchorFill()
ZO_Scroll_SetUseFadeGradient(scrollContainer, false)
ZO_Scroll_SetHideScrollbarOnDisable(scrollContainer, false)
ZO_VerticalScrollbarBase_OnMouseExit(scrollContainer:GetNamedChild("ScrollBar")) -- scrollbar initialization seems to be broken so we force it to update the correct alpha value
local scroll = GetControl(scrollContainer, "ScrollChild")
self.scroll = scroll
self.scrollContainer = scrollContainer
local bg = wm:CreateControl(nil, scrollContainer, CT_BACKDROP)
bg:SetAnchor(TOPLEFT, scrollContainer, TOPLEFT, 0, -3)
bg:SetAnchor(BOTTOMRIGHT, scrollContainer, BOTTOMRIGHT, 2, 5)
bg:SetEdgeTexture("EsoUI\\Art\\Tooltips\\UI-Border.dds", 128, 16)
bg:SetCenterTexture("EsoUI\\Art\\Tooltips\\UI-TooltipCenter.dds")
bg:SetInsets(16, 16, -16, -16)
local mungeOverlay = wm:CreateControl(nil, bg, CT_TEXTURE)
mungeOverlay:SetTexture("EsoUI/Art/Tooltips/munge_overlay.dds")
mungeOverlay:SetDrawLevel(1)
mungeOverlay:SetAddressMode(TEX_MODE_WRAP)
mungeOverlay:SetAnchorFill()
local mouseOver = wm:CreateControl(nil, scrollContainer, CT_TEXTURE)
mouseOver:SetDrawLevel(2)
mouseOver:SetTexture("EsoUI/Art/Buttons/minmax_mouseover.dds")
mouseOver:SetHidden(true)
local function IconFactory(pool)
local icon = wm:CreateControl(name .. "Entry" .. pool:GetNextControlId(), scroll, CT_TEXTURE)
icon:SetMouseEnabled(true)
icon:SetDrawLevel(3)
icon:SetHandler("OnMouseEnter", function()
mouseOver:SetAnchor(TOPLEFT, icon, TOPLEFT, 0, 0)
mouseOver:SetAnchor(BOTTOMRIGHT, icon, BOTTOMRIGHT, 0, 0)
mouseOver:SetHidden(false)
if self.customOnMouseEnter then
self.customOnMouseEnter(icon)
else
self:OnMouseEnter(icon)
end
end)
icon:SetHandler("OnMouseExit", function()
mouseOver:ClearAnchors()
mouseOver:SetHidden(true)
if self.customOnMouseExit then
self.customOnMouseExit(icon)
else
self:OnMouseExit(icon)
end
end)
icon:SetHandler("OnMouseUp", function(control, ...)
PlaySound("Click")
icon.OnSelect(icon, icon.texture)
self:Clear()
end)
return icon
end
local function ResetFunction(icon)
icon:ClearAnchors()
end
self.iconPool = ZO_ObjectPool:New(IconFactory, ResetFunction)
self:SetMaxColumns(1)
self.icons = {}
self.color = ZO_DEFAULT_ENABLED_COLOR
EVENT_MANAGER:RegisterForEvent(name .. "_OnGlobalMouseUp", EVENT_GLOBAL_MOUSE_UP, function()
if self.refCount ~= nil then
local moc = wm:GetMouseOverControl()
if(moc:GetOwningWindow() ~= control) then
self.refCount = self.refCount - 1
if self.refCount <= 0 then
self:Clear()
end
end
end
end)
end
function IconPickerMenu:OnMouseEnter(icon)
InitializeTooltip(InformationTooltip, icon, TOPLEFT, 0, 0, BOTTOMRIGHT)
SetTooltipText(InformationTooltip, LAM.util.GetStringFromValue(icon.tooltip))
InformationTooltipTopLevel:BringWindowToTop()
end
function IconPickerMenu:OnMouseExit(icon)
ClearTooltip(InformationTooltip)
end
function IconPickerMenu:SetMaxColumns(value)
self.maxCols = value ~= nil and value or 5
end
local DEFAULT_SIZE = 28
function IconPickerMenu:SetIconSize(value)
local iconSize = DEFAULT_SIZE
if value ~= nil then iconSize = math.max(iconSize, value) end
self.iconSize = iconSize
end
function IconPickerMenu:SetVisibleRows(value)
self.visibleRows = value ~= nil and value or 4.5
end
function IconPickerMenu:SetMouseHandlers(onEnter, onExit)
self.customOnMouseEnter = onEnter
self.customOnMouseExit = onExit
end
function IconPickerMenu:UpdateDimensions()
local iconSize = self.iconSize
local width = iconSize * self.maxCols + 20
local height = iconSize * self.visibleRows
self.control:SetDimensions(width, height)
local icons = self.icons
for i = 1, #icons do
local icon = icons[i]
icon:SetDimensions(iconSize, iconSize)
end
end
function IconPickerMenu:UpdateAnchors()
local iconSize = self.iconSize
local col, maxCols = 1, self.maxCols
local previousCol, previousRow
local scroll = self.scroll
local icons = self.icons
for i = 1, #icons do
local icon = icons[i]
icon:ClearAnchors()
if i == 1 then
icon:SetAnchor(TOPLEFT, scroll, TOPLEFT, 0, 0)
previousRow = icon
elseif col == 1 then
icon:SetAnchor(TOPLEFT, previousRow, BOTTOMLEFT, 0, 0)
previousRow = icon
else
icon:SetAnchor(TOPLEFT, previousCol, TOPRIGHT, 0, 0)
end
previousCol = icon
col = col >= maxCols and 1 or col + 1
end
end
function IconPickerMenu:Clear()
self.icons = {}
self.iconPool:ReleaseAllObjects()
self.control:SetHidden(true)
self.color = ZO_DEFAULT_ENABLED_COLOR
self.refCount = nil
self.parent = nil
self.customOnMouseEnter = nil
self.customOnMouseExit = nil
end
function IconPickerMenu:AddIcon(texturePath, callback, tooltip)
local icon, key = self.iconPool:AcquireObject()
icon:SetTexture(texturePath)
icon:SetColor(self.color:UnpackRGBA())
icon.texture = texturePath
icon.tooltip = tooltip
icon.OnSelect = callback
self.icons[#self.icons + 1] = icon
end
function IconPickerMenu:Show(parent)
if #self.icons == 0 then return false end
if not self.control:IsHidden() then self:Clear() return false end
self:UpdateDimensions()
self:UpdateAnchors()
local control = self.control
control:ClearAnchors()
control:SetAnchor(TOPLEFT, parent, BOTTOMLEFT, 0, 8)
control:SetHidden(false)
control:BringWindowToTop()
self.parent = parent
self.refCount = 2
return true
end
function IconPickerMenu:SetColor(color)
local icons = self.icons
self.color = color
for i = 1, #icons do
local icon = icons[i]
icon:SetColor(color:UnpackRGBA())
end
end
-------------------------------------------------------------
local function UpdateChoices(control, choices, choicesTooltips)
local data = control.data
if not choices then
choices, choicesTooltips = data.choices, data.choicesTooltips or {}
end
local addedChoices = {}
local iconPicker = LAM.util.GetIconPickerMenu()
iconPicker:Clear()
for i = 1, #choices do
local texture = choices[i]
if not addedChoices[texture] then -- remove duplicates
iconPicker:AddIcon(choices[i], function(self, texture)
control.icon:SetTexture(texture)
data.setFunc(texture)
LAM.util.RequestRefreshIfNeeded(control)
end, LAM.util.GetStringFromValue(choicesTooltips[i]))
addedChoices[texture] = true
end
end
end
local function IsDisabled(control)
if type(control.data.disabled) == "function" then
return control.data.disabled()
else
return control.data.disabled
end
end
local function SetColor(control, color)
local icon = control.icon
if IsDisabled(control) then
icon:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA())
else
icon.color = color or control.data.defaultColor or ZO_DEFAULT_ENABLED_COLOR
icon:SetColor(icon.color:UnpackRGBA())
end
local iconPicker = LAM.util.GetIconPickerMenu()
if iconPicker.parent == control.container and not iconPicker.control:IsHidden() then
iconPicker:SetColor(icon.color)
end
end
local function UpdateDisabled(control)
local disable = IsDisabled(control)
control.dropdown:SetMouseEnabled(not disable)
control.dropdownButton:SetEnabled(not disable)
local iconPicker = LAM.util.GetIconPickerMenu()
if iconPicker.parent == control.container and not iconPicker.control:IsHidden() then
iconPicker:Clear()
end
SetColor(control, control.icon.color)
if disable then
control.label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA())
else
control.label:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA())
end
end
local function UpdateValue(control, forceDefault, value)
if forceDefault then --if we are forcing defaults
value = LAM.util.GetDefaultValue(control.data.default)
control.data.setFunc(value)
control.icon:SetTexture(value)
elseif value then
control.data.setFunc(value)
--after setting this value, let's refresh the others to see if any should be disabled or have their settings changed
LAM.util.RequestRefreshIfNeeded(control)
else
value = control.data.getFunc()
control.icon:SetTexture(value)
end
end
local MIN_HEIGHT = 26
local HALF_WIDTH_LINE_SPACING = 2
local function SetIconSize(control, size)
local icon = control.icon
icon.size = size
icon:SetDimensions(size, size)
local height = size + 4
control.dropdown:SetDimensions(size + 20, height)
height = math.max(height, MIN_HEIGHT)
control.container:SetHeight(height)
if control.lineControl then
control.lineControl:SetHeight(MIN_HEIGHT + size + HALF_WIDTH_LINE_SPACING)
else
control:SetHeight(height)
end
local iconPicker = LAM.util.GetIconPickerMenu()
if iconPicker.parent == control.container and not iconPicker.control:IsHidden() then
iconPicker:SetIconSize(size)
iconPicker:UpdateDimensions()
iconPicker:UpdateAnchors()
end
end
function LAMCreateControl.iconpicker(parent, iconpickerData, controlName)
local control = LAM.util.CreateLabelAndContainerControl(parent, iconpickerData, controlName)
local function ShowIconPicker()
local iconPicker = LAM.util.GetIconPickerMenu()
if iconPicker.parent == control.container then
iconPicker:Clear()
else
iconPicker:SetMaxColumns(iconpickerData.maxColumns)
iconPicker:SetVisibleRows(iconpickerData.visibleRows)
iconPicker:SetIconSize(control.icon.size)
UpdateChoices(control)
iconPicker:SetColor(control.icon.color)
if iconpickerData.beforeShow then
if iconpickerData.beforeShow(control, iconPicker) then
iconPicker:Clear()
return
end
end
iconPicker:Show(control.container)
end
end
local iconSize = iconpickerData.iconSize ~= nil and iconpickerData.iconSize or DEFAULT_SIZE
control.dropdown = wm:CreateControl(nil, control.container, CT_CONTROL)
local dropdown = control.dropdown
dropdown:SetAnchor(LEFT, control.container, LEFT, 0, 0)
dropdown:SetMouseEnabled(true)
dropdown:SetHandler("OnMouseUp", ShowIconPicker)
dropdown:SetHandler("OnMouseEnter", function() ZO_Options_OnMouseEnter(control) end)
dropdown:SetHandler("OnMouseExit", function() ZO_Options_OnMouseExit(control) end)
control.icon = wm:CreateControl(nil, dropdown, CT_TEXTURE)
local icon = control.icon
icon:SetAnchor(LEFT, dropdown, LEFT, 3, 0)
icon:SetDrawLevel(2)
local dropdownButton = wm:CreateControlFromVirtual(nil, dropdown, "ZO_DropdownButton")
dropdownButton:SetDimensions(16, 16)
dropdownButton:SetHandler("OnClicked", ShowIconPicker)
dropdownButton:SetAnchor(RIGHT, dropdown, RIGHT, -3, 0)
control.dropdownButton = dropdownButton
control.bg = wm:CreateControl(nil, dropdown, CT_BACKDROP)
local bg = control.bg
bg:SetAnchor(TOPLEFT, dropdown, TOPLEFT, 0, -3)
bg:SetAnchor(BOTTOMRIGHT, dropdown, BOTTOMRIGHT, 2, 5)
bg:SetEdgeTexture("EsoUI/Art/Tooltips/UI-Border.dds", 128, 16)
bg:SetCenterTexture("EsoUI/Art/Tooltips/UI-TooltipCenter.dds")
bg:SetInsets(16, 16, -16, -16)
local mungeOverlay = wm:CreateControl(nil, bg, CT_TEXTURE)
mungeOverlay:SetTexture("EsoUI/Art/Tooltips/munge_overlay.dds")
mungeOverlay:SetDrawLevel(1)
mungeOverlay:SetAddressMode(TEX_MODE_WRAP)
mungeOverlay:SetAnchorFill()
if iconpickerData.warning ~= nil or iconpickerData.requiresReload then
control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon")
control.warning:SetAnchor(RIGHT, control.container, LEFT, -5, 0)
control.UpdateWarning = LAM.util.UpdateWarning
control:UpdateWarning()
end
control.UpdateChoices = UpdateChoices
control.UpdateValue = UpdateValue
control:UpdateValue()
control.SetColor = SetColor
control:SetColor()
control.SetIconSize = SetIconSize
control:SetIconSize(iconSize)
if iconpickerData.disabled ~= nil then
control.UpdateDisabled = UpdateDisabled
control:UpdateDisabled()
end
LAM.util.RegisterForRefreshIfNeeded(control)
LAM.util.RegisterForReloadIfNeeded(control)
return control
end

View File

@ -0,0 +1,168 @@
--[[panelData = {
type = "panel",
name = "Window Title", -- or string id or function returning a string
displayName = "My Longer Window Title", -- or string id or function returning a string (optional) (can be useful for long addon names or if you want to colorize it)
author = "Seerah", -- or string id or function returning a string (optional)
version = "2.0", -- or string id or function returning a string (optional)
website = "http://www.esoui.com/downloads/info7-LibAddonMenu.html", -- URL of website where the addon can be updated or function (optional)
feedback = "https://www.esoui.com/portal.php?uid=5815", -- URL of website where feedback/feature requests/bugs can be reported for the addon or function (optional)
translation = "https://www.esoui.com/portal.php?uid=5815", -- URL of website where translation texts of the addon can be helped with or function (optional)
donation = "http://www.esoui.com/downloads/info7-LibAddonMenu.html", -- URL of website where a donation for the addon author can be raised or function (optional)
keywords = "settings", -- additional keywords for search filter (it looks for matches in name..keywords..author) (optional)
slashCommand = "/myaddon", -- will register a keybind to open to this panel (don't forget to include the slash!) (optional)
registerForRefresh = true, -- boolean will refresh all options controls when a setting is changed and when the panel is shown (optional)
registerForDefaults = true, -- boolean will set all options controls back to default values (optional)
resetFunc = function() print("defaults reset") end, -- custom function to run after settings are reset to defaults (optional)
} ]]
local widgetVersion = 15
local LAM = LibStub("LibAddonMenu-2.0")
if not LAM:RegisterWidget("panel", widgetVersion) then return end
local wm = WINDOW_MANAGER
local cm = CALLBACK_MANAGER
local function RefreshPanel(control)
local panel = LAM.util.GetTopPanel(control) --callback can be fired by a single control, by the panel showing or by a nested submenu
if LAM.currentAddonPanel ~= panel or not LAM.currentPanelOpened then return end -- we refresh it later when the panel is opened
local panelControls = panel.controlsToRefresh
for i = 1, #panelControls do
local updateControl = panelControls[i]
if updateControl ~= control and updateControl.UpdateValue then
updateControl:UpdateValue()
end
if updateControl.UpdateDisabled then
updateControl:UpdateDisabled()
end
if updateControl.UpdateWarning then
updateControl:UpdateWarning()
end
end
end
local function ForceDefaults(panel)
local panelControls = panel.controlsToRefresh
for i = 1, #panelControls do
local updateControl = panelControls[i]
if updateControl.UpdateValue and updateControl.data.default ~= nil then
updateControl:UpdateValue(true)
end
end
if panel.data.resetFunc then
panel.data.resetFunc()
end
cm:FireCallbacks("LAM-RefreshPanel", panel)
end
local callbackRegistered = false
LAMCreateControl.scrollCount = LAMCreateControl.scrollCount or 1
local SEPARATOR = " - "
local COLORED_SEPARATOR = ZO_WHITE:Colorize(SEPARATOR)
local LINK_COLOR = ZO_ColorDef:New("5959D5")
local LINK_MOUSE_OVER_COLOR = ZO_ColorDef:New("B8B8D3")
local LINK_COLOR_DONATE = ZO_ColorDef:New("FFD700") -- golden
local LINK_MOUSE_OVER_COLOR_DONATE = ZO_ColorDef:New("FFF6CC")
local function CreateButtonControl(control, label, clickAction, relativeTo)
local button = wm:CreateControl(nil, control, CT_BUTTON)
button:SetClickSound("Click")
button:SetFont(LAM.util.L["PANEL_INFO_FONT"])
button:SetNormalFontColor(LINK_COLOR:UnpackRGBA())
button:SetMouseOverFontColor(LINK_MOUSE_OVER_COLOR:UnpackRGBA())
local OnClicked
local actionType = type(clickAction)
if actionType == "string" then
OnClicked = function() RequestOpenUnsafeURL(clickAction) end
elseif actionType == "function" then
OnClicked = clickAction
end
button:SetHandler("OnClicked", OnClicked)
if relativeTo then
button:SetAnchor(TOPLEFT, relativeTo, TOPRIGHT, 0, 0)
button:SetText(COLORED_SEPARATOR .. label)
else
button:SetAnchor(TOPLEFT, control.label, BOTTOMLEFT, 0, -2)
button:SetText(label)
end
button:SetDimensions(button:GetLabelControl():GetTextDimensions())
return button
end
function LAMCreateControl.panel(parent, panelData, controlName)
local control = wm:CreateControl(controlName, parent, CT_CONTROL)
control.label = wm:CreateControlFromVirtual(nil, control, "ZO_Options_SectionTitleLabel")
local label = control.label
label:SetAnchor(TOPLEFT, control, TOPLEFT, 0, 4)
label:SetText(LAM.util.GetStringFromValue(panelData.displayName or panelData.name))
local previousInfoControl
if panelData.author or panelData.version then
control.info = wm:CreateControl(nil, control, CT_LABEL)
local info = control.info
info:SetFont(LAM.util.L["PANEL_INFO_FONT"])
info:SetAnchor(TOPLEFT, label, BOTTOMLEFT, 0, -2)
local output = {}
if panelData.author then
output[#output + 1] = zo_strformat(LAM.util.L["AUTHOR"], LAM.util.GetStringFromValue(panelData.author))
end
if panelData.version then
output[#output + 1] = zo_strformat(LAM.util.L["VERSION"], LAM.util.GetStringFromValue(panelData.version))
end
info:SetText(table.concat(output, SEPARATOR))
previousInfoControl = info
end
if panelData.website then
control.website = CreateButtonControl(control, LAM.util.L["WEBSITE"], panelData.website, previousInfoControl)
previousInfoControl = control.website
end
if panelData.feedback then
control.feedback = CreateButtonControl(control, LAM.util.L["FEEDBACK"], panelData.feedback, previousInfoControl)
previousInfoControl = control.feedback
end
if panelData.translation then
control.translation = CreateButtonControl(control, LAM.util.L["TRANSLATION"], panelData.translation, previousInfoControl)
previousInfoControl = control.translation
end
if panelData.donation then
control.donation = CreateButtonControl(control, LAM.util.L["DONATION"], panelData.donation, previousInfoControl)
local donation = control.donation
previousInfoControl = donation
donation:SetNormalFontColor(LINK_COLOR_DONATE:UnpackRGBA())
donation:SetMouseOverFontColor(LINK_MOUSE_OVER_COLOR_DONATE:UnpackRGBA())
end
control.container = wm:CreateControlFromVirtual("LAMAddonPanelContainer"..LAMCreateControl.scrollCount, control, "ZO_ScrollContainer")
LAMCreateControl.scrollCount = LAMCreateControl.scrollCount + 1
local container = control.container
container:SetAnchor(TOPLEFT, control.info or label, BOTTOMLEFT, 0, 20)
container:SetAnchor(BOTTOMRIGHT, control, BOTTOMRIGHT, -3, -3)
control.scroll = GetControl(control.container, "ScrollChild")
control.scroll:SetResizeToFitPadding(0, 20)
if panelData.registerForRefresh and not callbackRegistered then --don't want to register our callback more than once
cm:RegisterCallback("LAM-RefreshPanel", RefreshPanel)
callbackRegistered = true
end
control.ForceDefaults = ForceDefaults
control.RefreshPanel = LAM.util.RequestRefreshIfNeeded
control.data = panelData
control.controlsToRefresh = {}
return control
end

View File

@ -0,0 +1,220 @@
--[[sliderData = {
type = "slider",
name = "My Slider", -- or string id or function returning a string
getFunc = function() return db.var end,
setFunc = function(value) db.var = value doStuff() end,
min = 0,
max = 20,
step = 1, -- (optional)
clampInput = true, -- boolean, if set to false the input won't clamp to min and max and allow any number instead (optional)
clampFunction = function(value, min, max) return math.max(math.min(value, max), min) end, -- function that is called to clamp the value (optional)
decimals = 0, -- when specified the input value is rounded to the specified number of decimals (optional)
autoSelect = false, -- boolean, automatically select everything in the text input field when it gains focus (optional)
inputLocation = "below", -- or "right", determines where the input field is shown. This should not be used within the addon menu and is for custom sliders (optional)
tooltip = "Slider's tooltip text.", -- or string id or function returning a string (optional)
width = "full", -- or "half" (optional)
disabled = function() return db.someBooleanSetting end, --or boolean (optional)
warning = "May cause permanent awesomeness.", -- or string id or function returning a string (optional)
requiresReload = false, -- boolean, if set to true, the warning text will contain a notice that changes are only applied after an UI reload and any change to the value will make the "Apply Settings" button appear on the panel which will reload the UI when pressed (optional)
default = defaults.var, -- default value or function that returns the default value (optional)
reference = "MyAddonSlider" -- unique global reference to control (optional)
} ]]
local widgetVersion = 13
local LAM = LibStub("LibAddonMenu-2.0")
if not LAM:RegisterWidget("slider", widgetVersion) then return end
local wm = WINDOW_MANAGER
local strformat = string.format
local function RoundDecimalToPlace(d, place)
return tonumber(strformat("%." .. tostring(place) .. "f", d))
end
local function ClampValue(value, min, max)
return math.max(math.min(value, max), min)
end
local function UpdateDisabled(control)
local disable
if type(control.data.disabled) == "function" then
disable = control.data.disabled()
else
disable = control.data.disabled
end
control.slider:SetEnabled(not disable)
control.slidervalue:SetEditEnabled(not disable)
if disable then
control.label:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA())
control.minText:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA())
control.maxText:SetColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA())
control.slidervalue:SetColor(ZO_DEFAULT_DISABLED_MOUSEOVER_COLOR:UnpackRGBA())
else
control.label:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA())
control.minText:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA())
control.maxText:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA())
control.slidervalue:SetColor(ZO_DEFAULT_ENABLED_COLOR:UnpackRGBA())
end
end
local function UpdateValue(control, forceDefault, value)
if forceDefault then --if we are forcing defaults
value = LAM.util.GetDefaultValue(control.data.default)
control.data.setFunc(value)
elseif value then
if control.data.decimals then
value = RoundDecimalToPlace(value, control.data.decimals)
end
if control.data.clampInput ~= false then
local clamp = control.data.clampFunction or ClampValue
value = clamp(value, control.data.min, control.data.max)
end
control.data.setFunc(value)
--after setting this value, let's refresh the others to see if any should be disabled or have their settings changed
LAM.util.RequestRefreshIfNeeded(control)
else
value = control.data.getFunc()
end
control.slider:SetValue(value)
control.slidervalue:SetText(value)
end
function LAMCreateControl.slider(parent, sliderData, controlName)
local control = LAM.util.CreateLabelAndContainerControl(parent, sliderData, controlName)
local isInputOnRight = sliderData.inputLocation == "right"
--skipping creating the backdrop... Is this the actual slider texture?
control.slider = wm:CreateControl(nil, control.container, CT_SLIDER)
local slider = control.slider
slider:SetAnchor(TOPLEFT)
slider:SetHeight(14)
if(isInputOnRight) then
slider:SetAnchor(TOPRIGHT, nil, nil, -60)
else
slider:SetAnchor(TOPRIGHT)
end
slider:SetMouseEnabled(true)
slider:SetOrientation(ORIENTATION_HORIZONTAL)
--put nil for highlighted texture file path, and what look to be texture coords
slider:SetThumbTexture("EsoUI\\Art\\Miscellaneous\\scrollbox_elevator.dds", "EsoUI\\Art\\Miscellaneous\\scrollbox_elevator_disabled.dds", nil, 8, 16)
local minValue = sliderData.min
local maxValue = sliderData.max
slider:SetMinMax(minValue, maxValue)
slider:SetHandler("OnMouseEnter", function() ZO_Options_OnMouseEnter(control) end)
slider:SetHandler("OnMouseExit", function() ZO_Options_OnMouseExit(control) end)
slider.bg = wm:CreateControl(nil, slider, CT_BACKDROP)
local bg = slider.bg
bg:SetCenterColor(0, 0, 0)
bg:SetAnchor(TOPLEFT, slider, TOPLEFT, 0, 4)
bg:SetAnchor(BOTTOMRIGHT, slider, BOTTOMRIGHT, 0, -4)
bg:SetEdgeTexture("EsoUI\\Art\\Tooltips\\UI-SliderBackdrop.dds", 32, 4)
control.minText = wm:CreateControl(nil, slider, CT_LABEL)
local minText = control.minText
minText:SetFont("ZoFontGameSmall")
minText:SetAnchor(TOPLEFT, slider, BOTTOMLEFT)
minText:SetText(sliderData.min)
control.maxText = wm:CreateControl(nil, slider, CT_LABEL)
local maxText = control.maxText
maxText:SetFont("ZoFontGameSmall")
maxText:SetAnchor(TOPRIGHT, slider, BOTTOMRIGHT)
maxText:SetText(sliderData.max)
control.slidervalueBG = wm:CreateControlFromVirtual(nil, slider, "ZO_EditBackdrop")
if(isInputOnRight) then
control.slidervalueBG:SetDimensions(60, 26)
control.slidervalueBG:SetAnchor(LEFT, slider, RIGHT, 5, 0)
else
control.slidervalueBG:SetDimensions(50, 16)
control.slidervalueBG:SetAnchor(TOP, slider, BOTTOM, 0, 0)
end
control.slidervalue = wm:CreateControlFromVirtual(nil, control.slidervalueBG, "ZO_DefaultEditForBackdrop")
local slidervalue = control.slidervalue
slidervalue:ClearAnchors()
slidervalue:SetAnchor(TOPLEFT, control.slidervalueBG, TOPLEFT, 3, 1)
slidervalue:SetAnchor(BOTTOMRIGHT, control.slidervalueBG, BOTTOMRIGHT, -3, -1)
slidervalue:SetTextType(TEXT_TYPE_NUMERIC)
if(isInputOnRight) then
slidervalue:SetFont("ZoFontGameLarge")
else
slidervalue:SetFont("ZoFontGameSmall")
end
local isHandlingChange = false
local function HandleValueChanged(value)
if isHandlingChange then return end
if sliderData.decimals then
value = RoundDecimalToPlace(value, sliderData.decimals)
end
isHandlingChange = true
slider:SetValue(value)
slidervalue:SetText(value)
isHandlingChange = false
end
slidervalue:SetHandler("OnEscape", function(self)
HandleValueChanged(sliderData.getFunc())
self:LoseFocus()
end)
slidervalue:SetHandler("OnEnter", function(self)
self:LoseFocus()
end)
slidervalue:SetHandler("OnFocusLost", function(self)
local value = tonumber(self:GetText())
control:UpdateValue(false, value)
end)
slidervalue:SetHandler("OnTextChanged", function(self)
local input = self:GetText()
if(#input > 1 and not input:sub(-1):match("[0-9]")) then return end
local value = tonumber(input)
if(value) then
HandleValueChanged(value)
end
end)
if(sliderData.autoSelect) then
ZO_PreHookHandler(slidervalue, "OnFocusGained", function(self)
self:SelectAll()
end)
end
local range = maxValue - minValue
slider:SetValueStep(sliderData.step or 1)
slider:SetHandler("OnValueChanged", function(self, value, eventReason)
if eventReason == EVENT_REASON_SOFTWARE then return end
HandleValueChanged(value)
end)
slider:SetHandler("OnSliderReleased", function(self, value)
if self:GetEnabled() then
control:UpdateValue(false, value)
end
end)
slider:SetHandler("OnMouseWheel", function(self, value)
if(not self:GetEnabled()) then return end
local new_value = (tonumber(slidervalue:GetText()) or sliderData.min or 0) + ((sliderData.step or 1) * value)
control:UpdateValue(false, new_value)
end)
if sliderData.warning ~= nil or sliderData.requiresReload then
control.warning = wm:CreateControlFromVirtual(nil, control, "ZO_Options_WarningIcon")
control.warning:SetAnchor(RIGHT, slider, LEFT, -5, 0)
control.UpdateWarning = LAM.util.UpdateWarning
control:UpdateWarning()
end
control.UpdateValue = UpdateValue
control:UpdateValue()
if sliderData.disabled ~= nil then
control.UpdateDisabled = UpdateDisabled
control:UpdateDisabled()
end
LAM.util.RegisterForRefreshIfNeeded(control)
LAM.util.RegisterForReloadIfNeeded(control)
return control
end

View File

@ -0,0 +1,182 @@
--[[submenuData = {
type = "submenu",
name = "Submenu Title", -- or string id or function returning a string
icon = "path/to/my/icon.dds", -- or function returning a string (optional)
iconTextureCoords = {left, right, top, bottom}, -- or function returning a table (optional)
tooltip = "My submenu tooltip", -- or string id or function returning a string (optional)
controls = {sliderData, buttonData} -- used by LAM (optional)
disabled = function() return db.someBooleanSetting end, -- or boolean (optional)
disabledLabel = function() return db.someBooleanSetting end, -- or boolean (optional)
reference = "MyAddonSubmenu" -- unique global reference to control (optional)
} ]]
local widgetVersion = 13
local LAM = LibStub("LibAddonMenu-2.0")
if not LAM:RegisterWidget("submenu", widgetVersion) then return end
local wm = WINDOW_MANAGER
local am = ANIMATION_MANAGER
local ICON_SIZE = 32
local GetDefaultValue = LAM.util.GetDefaultValue
local GetColorForState = LAM.util.GetColorForState
local function UpdateDisabled(control)
local disable = GetDefaultValue(control.data.disabled)
if disable ~= control.disabled then
local color = GetColorForState(disable)
if disable and control.open then
control.open = false
control.animation:PlayFromStart()
end
control.arrow:SetColor(color:UnpackRGBA())
control.disabled = disable
end
local disableLabel = control.disabled or GetDefaultValue(control.data.disabledLabel)
if disableLabel ~= control.disabledLabel then
local color = GetColorForState(disableLabel)
control.label:SetColor(color:UnpackRGBA())
if(control.icon) then
control.icon:SetDesaturation(disableLabel and 1 or 0)
end
control.disabledLabel = disableLabel
end
end
local function UpdateValue(control)
control.label:SetText(LAM.util.GetStringFromValue(control.data.name))
if control.icon then
control.icon:SetTexture(GetDefaultValue(control.data.icon))
if(control.data.iconTextureCoords) then
local coords = GetDefaultValue(control.data.iconTextureCoords)
control.icon:SetTextureCoords(unpack(coords))
end
end
if control.data.tooltip then
control.label.data.tooltipText = LAM.util.GetStringFromValue(control.data.tooltip)
end
end
local function AnimateSubmenu(clicked)
local control = clicked:GetParent()
if control.disabled then return end
control.open = not control.open
if control.open then
control.animation:PlayFromStart()
else
control.animation:PlayFromEnd()
end
end
function LAMCreateControl.submenu(parent, submenuData, controlName)
local width = parent:GetWidth() - 45
local control = wm:CreateControl(controlName or submenuData.reference, parent.scroll or parent, CT_CONTROL)
control.panel = parent
control.data = submenuData
control.label = wm:CreateControlFromVirtual(nil, control, "ZO_Options_SectionTitleLabel")
local label = control.label
label:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS)
label:SetText(LAM.util.GetStringFromValue(submenuData.name))
label:SetMouseEnabled(true)
if submenuData.icon then
control.icon = wm:CreateControl(nil, control, CT_TEXTURE)
local icon = control.icon
icon:SetTexture(GetDefaultValue(submenuData.icon))
if(submenuData.iconTextureCoords) then
local coords = GetDefaultValue(submenuData.iconTextureCoords)
icon:SetTextureCoords(unpack(coords))
end
icon:SetDimensions(ICON_SIZE, ICON_SIZE)
icon:SetAnchor(TOPLEFT, control, TOPLEFT, 5, 5)
icon:SetMouseEnabled(true)
icon:SetDrawLayer(DL_CONTROLS)
label:SetAnchor(TOP, control, TOP, 0, 5, ANCHOR_CONSTRAINS_Y)
label:SetAnchor(LEFT, icon, RIGHT, 10, 0, ANCHOR_CONSTRAINS_X)
label:SetDimensions(width - ICON_SIZE - 5, 30)
else
label:SetAnchor(TOPLEFT, control, TOPLEFT, 5, 5)
label:SetDimensions(width, 30)
end
if submenuData.tooltip then
label.data = {tooltipText = LAM.util.GetStringFromValue(submenuData.tooltip)}
label:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter)
label:SetHandler("OnMouseExit", ZO_Options_OnMouseExit)
if control.icon then
control.icon.data = label.data
control.icon:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter)
control.icon:SetHandler("OnMouseExit", ZO_Options_OnMouseExit)
end
end
control.scroll = wm:CreateControl(nil, control, CT_SCROLL)
local scroll = control.scroll
scroll:SetParent(control)
scroll:SetAnchor(TOPLEFT, control.icon or label, BOTTOMLEFT, 0, 10)
scroll:SetDimensionConstraints(width + 5, 0, width + 5, 0)
control.bg = wm:CreateControl(nil, control.icon or label, CT_BACKDROP)
local bg = control.bg
bg:SetAnchor(TOPLEFT, control.icon or label, TOPLEFT, -5, -5)
bg:SetAnchor(BOTTOMRIGHT, scroll, BOTTOMRIGHT, -7, 0)
bg:SetEdgeTexture("EsoUI\\Art\\Tooltips\\UI-Border.dds", 128, 16)
bg:SetCenterTexture("EsoUI\\Art\\Tooltips\\UI-TooltipCenter.dds")
bg:SetInsets(16, 16, -16, -16)
bg:SetDrawLayer(DL_BACKGROUND)
control.arrow = wm:CreateControl(nil, bg, CT_TEXTURE)
local arrow = control.arrow
arrow:SetDimensions(28, 28)
arrow:SetTexture("EsoUI\\Art\\Miscellaneous\\list_sortdown.dds") --list_sortup for the other way
arrow:SetAnchor(TOPRIGHT, bg, TOPRIGHT, -5, 5)
--figure out the cool animation later...
control.animation = am:CreateTimeline()
local animation = control.animation
animation:SetPlaybackType(ANIMATION_SIZE, 0) --2nd arg = loop count
control:SetResizeToFitDescendents(true)
control.open = false
label:SetHandler("OnMouseUp", AnimateSubmenu)
if(control.icon) then
control.icon:SetHandler("OnMouseUp", AnimateSubmenu)
end
animation:SetHandler("OnStop", function(self, completedPlaying)
scroll:SetResizeToFitDescendents(control.open)
if control.open then
control.arrow:SetTexture("EsoUI\\Art\\Miscellaneous\\list_sortup.dds")
scroll:SetResizeToFitPadding(5, 20)
else
control.arrow:SetTexture("EsoUI\\Art\\Miscellaneous\\list_sortdown.dds")
scroll:SetResizeToFitPadding(5, 0)
scroll:SetHeight(0)
end
end)
--small strip at the bottom of the submenu that you can click to close it
control.btmToggle = wm:CreateControl(nil, control, CT_TEXTURE)
local btmToggle = control.btmToggle
btmToggle:SetMouseEnabled(true)
btmToggle:SetAnchor(BOTTOMLEFT, control.scroll, BOTTOMLEFT)
btmToggle:SetAnchor(BOTTOMRIGHT, control.scroll, BOTTOMRIGHT)
btmToggle:SetHeight(15)
btmToggle:SetAlpha(0)
btmToggle:SetHandler("OnMouseUp", AnimateSubmenu)
control.UpdateValue = UpdateValue
if submenuData.disabled ~= nil or submenuData.disabledLabel ~= nil then
control.UpdateDisabled = UpdateDisabled
control:UpdateDisabled()
end
LAM.util.RegisterForRefreshIfNeeded(control)
return control
end

View File

@ -0,0 +1,45 @@
--[[textureData = {
type = "texture",
image = "file/path.dds",
imageWidth = 64, -- max of 250 for half width, 510 for full
imageHeight = 32, -- max of 100
tooltip = "Image's tooltip text.", -- or string id or function returning a string (optional)
width = "full", -- or "half" (optional)
reference = "MyAddonTexture" -- unique global reference to control (optional)
} ]]
-- TODO: add texture coords support?
local widgetVersion = 9
local LAM = LibStub("LibAddonMenu-2.0")
if not LAM:RegisterWidget("texture", widgetVersion) then return end
local wm = WINDOW_MANAGER
local MIN_HEIGHT = 26
function LAMCreateControl.texture(parent, textureData, controlName)
local control = LAM.util.CreateBaseControl(parent, textureData, controlName)
local width = control:GetWidth()
control:SetResizeToFitDescendents(true)
if control.isHalfWidth then --note these restrictions
control:SetDimensionConstraints(width / 2, MIN_HEIGHT, width / 2, MIN_HEIGHT * 4)
else
control:SetDimensionConstraints(width, MIN_HEIGHT, width, MIN_HEIGHT * 4)
end
control.texture = wm:CreateControl(nil, control, CT_TEXTURE)
local texture = control.texture
texture:SetAnchor(CENTER)
texture:SetDimensions(textureData.imageWidth, textureData.imageHeight)
texture:SetTexture(textureData.image)
if textureData.tooltip then
texture:SetMouseEnabled(true)
texture.data = {tooltipText = LAM.util.GetStringFromValue(textureData.tooltip)}
texture:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter)
texture:SetHandler("OnMouseExit", ZO_Options_OnMouseExit)
end
return control
end

38
Libs/LibStub/LibStub.lua Normal file
View File

@ -0,0 +1,38 @@
-- LibStub is a simple versioning stub meant for use in Libraries. http://www.wowace.com/wiki/LibStub for more info
-- LibStub is hereby placed in the Public Domain Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke
-- LibStub developed for World of Warcraft by above members of the WowAce community.
-- Ported to Elder Scrolls Online by Seerah
local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 5
local LibStub = _G[LIBSTUB_MAJOR]
local strformat = string.format
if not LibStub or LibStub.minor < LIBSTUB_MINOR then
LibStub = LibStub or {libs = {}, minors = {} }
_G[LIBSTUB_MAJOR] = LibStub
LibStub.minor = LIBSTUB_MINOR
function LibStub:NewLibrary(major, minor)
assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)")
if type(minor) ~= "number" then
minor = assert(tonumber(zo_strmatch(minor, "%d+%.?%d*")), "Minor version must either be a number or contain a number.")
end
local oldminor = self.minors[major]
if oldminor and oldminor >= minor then return nil end
self.minors[major], self.libs[major] = minor, self.libs[major] or {}
return self.libs[major], oldminor
end
function LibStub:GetLibrary(major, silent)
if not self.libs[major] and not silent then
error(strformat("Cannot find a library instance of %q.", tostring(major)), 2)
end
return self.libs[major], self.minors[major]
end
function LibStub:IterateLibraries() return pairs(self.libs) end
setmetatable(LibStub, { __call = LibStub.GetLibrary })
end
LibStub.SILENT = true

View File

@ -1,33 +1,12 @@
# AchievementInfo # AchievementInfo
[![Version Status](https://monitoring.f-brinker.de/api/badge/18/status?style=plastic&upLabel=Up%20to%20date&downLabel=Outdated)](https://monitoring.f-brinker.de/status/eso) [![Build Status](https://drone.f-brinker.de/api/badges/fbrinker/elderscrolls-addon-achievementInfo/status.svg)](https://drone.f-brinker.de/fbrinker/elderscrolls-addon-achievementInfo)
[![Build Status](https://git.f-brinker.de/fbrinker/elderscrolls-addon-achievementInfo/actions/workflows/build.yaml/badge.svg)](https://git.f-brinker.de/fbrinker/elderscrolls-addon-achievementInfo/actions)
[![Latest Releases](https://badgen.net/badge/releases/latest)](https://git.f-brinker.de/fbrinker/elderscrolls-addon-achievementInfo/releases) [![Latest Releases](https://badgen.net/badge/releases/latest)](https://git.f-brinker.de/fbrinker/elderscrolls-addon-achievementInfo/releases)
[![Downloads](https://badgen.net/https/scripts.f-brinker.de/esoui-stats/badge-total.php?cache=1800)](https://www.esoui.com/downloads/info350-AchievementInfo.html)
[![Favorites](https://badgen.net/https/scripts.f-brinker.de/esoui-stats/badge-fav.php?cache=1800)](https://www.esoui.com/downloads/info350-AchievementInfo.html)
This is a **The Elderscrolls Online** addon. [See all details and the download @ESOUI](http://www.esoui.com/downloads/info350-AchievementInfo.html#info). This is an **The Elderscrolls Online** addon. [See all details and the download @ESOUI](http://www.esoui.com/downloads/info350-AchievementInfo.html#info).
[Issue-Tracker](https://git.f-brinker.de/fbrinker/elderscrolls-addon-achievementInfo/issues) [Issue-Tracker](https://git.f-brinker.de/fbrinker/elderscrolls-addon-achievementInfo/issues)
## Description
### What is this AddOn about?
I like achievements, and I like to know what to do to complete them and what type of achievements exist without browsing through the entire achievement catalog: This AddOn displays lightweight chat notifications if you make progress in an achievement (please see the screenshots).
### Features
* Shows chat notifications if you do something that is needed for an achievement
* Triggers on each action or just in x% steps of the achievement's requirements (configurable)
* Can show some details in the chat notification like (kill 250/1000 Humanoids)
* You can toggle the notifications for each category
* Lightweight: It is not always present and shows up only when necessary
* You can enable account-wide settings
![preview screenshot](screenshots/chat-1.jpg)
## Why is this a public project? ## Why is this a public project?
In case I quit or pause playing TESO and cannot maintain this addon, feel free to contribute to keep this up to date and running. In case I quit or pause playing TESO and cannot maintain this addon, feel free to contribute to keep this up to date and running.
@ -35,15 +14,9 @@ I'll still be available here and be able to update the ESOUI page.
## How to contribute? ## How to contribute?
**IMPORTANT: Github is a mirror.** Please contribute at [git.f-brinker.de/elderscrolls-addon-achievementInfo](https://git.f-brinker.de/fbrinker/elderscrolls-addon-achievementInfo) - You can log in with your Github or Gitlab account (OAuth2). **IMPORTANT: Github is a mirror.** Please contribute at [git.f-brinker.de/elderscrolls-addon-achievementInfo](https://git.f-brinker.de/fbrinker/elderscrolls-addon-achievementInfo) - You can login with your Github or Gitlab account (OAuth2).
Then, create a fork of the repository, do what you have to do, and create a pull-request afterward. Feel free to contact me any time. Then, create a fork of the repository, do what you have to do and create a pull-request afterwards. Feel free to contact me any time.
#### Linting #### Linting
Luacheck is used to check the LUA code. [Documentation](https://luacheck.readthedocs.io/en/stable/index.html) Luacheck is used to check the LUA code. [Documentation](https://luacheck.readthedocs.io/en/stable/index.html)
## API Version Upgrade
* Increment the API Version in the _AchievementInfo.txt_ file
* Commit: `git commit -am "New Api Version"`
* Add new Tag `git tag x.yz`
* Push `git push && git push --tags`

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB