Framework Update

This commit is contained in:
Tercio Jose
2024-04-29 18:19:26 -03:00
parent ab292b8a4f
commit 27f6d4757c
6 changed files with 658 additions and 194 deletions
+7
View File
@@ -11,6 +11,13 @@ local CreateFrame = CreateFrame
local PixelUtil = PixelUtil
local _
---@class df_menu : frame
---@field RefreshOptions fun()
---@field widget_list table
---@field widget_list_by_type table
---@field widgetids table
---@field GetWidgetById fun(optionsFrame: df_menu, id: string): table this should return a widget from the widgetids table
---@class df_menu_table : table
---@field text_template table
---@field id string an unique string or number to identify the button, from parent.widgetids[id], parent is the first argument of BuildMenu and BuildMenuVolatile
+5 -2
View File
@@ -137,7 +137,10 @@
---@field Math df_math
---@field FontOutlineFlags table<outline, boolean>
---@field table df_table_functions
---@field AnchorPoints string[]
---@field AnchorPoints string[] localized point names
---@field AnchorPointsByIndex string[] api point names
---@field AnchorPointsToInside table<anchorid, anchorid>
---@field InsidePointsToAnchor table<anchorid, anchorid>
---@field alias_text_colors table<string, number[]>
---@field ClassFileNameToIndex table<string, number> engClass -> classIndex
---@field ClientLanguage string
@@ -313,7 +316,7 @@
---@field CreateBorder fun(self:table, parent:frame, alpha1:number?, alpha2:number?, alpha3:number?) : frame
---@field CreateMenuWithGridScrollBox fun(self:table, parent:frame, name:string?, refreshMeFunc:function, refreshButtonFunc:function, clickFunc:function, onCreateButton:function, gridScrollBoxOptions:df_gridscrollbox_options) : df_gridscrollbox create a scrollbox with a grid layout to be used as a menu
---@field CreateSearchBox fun(self:table, parent:frame, callback:function) : df_searchbox
---@field
---@field ConvertAnchorPointToInside fun(self:table, anchorPoint:anchorid) : anchorid
---@field
+447 -181
View File
@@ -29,13 +29,15 @@ local _
---@field editingProfileTable table
---@field editingProfileMap table
---@field editingOptions df_editobjectoptions
---@field currentObjectNinePoints df_ninepoints
---@field editingExtraOptions table
---@field registeredObjectInfo df_editor_objectinfo
---@field moverGuideLines table<string, texture>
---@field onEditCallback function
---@field optionsFrame frame
---@field overTheTopFrame frame
---@field objectSelector df_scrollbox
---@field moverFrame frame
---@field moverFrames df_editor_mover[]
---@field canvasScrollBox df_canvasscrollbox
---@class df_editor_attribute
@@ -60,6 +62,19 @@ local _
---@field callback function?
---@field options df_editobjectoptions
---@field selectButton button
---@field refFrame frame
---@class df_editor_mover_movinginfo : table
---@field startX number
---@field startY number
---@field restingX number
---@field restingY number
---@class df_editor_mover : frame
---@field MovingInfo df_editor_mover_movinginfo
---@field ObjectBackgroundTexture texture
---@field MoverIcon texture
---@field bIsMoving boolean
--which object attributes are used to build the editor menu for each object type
local attributes = {
@@ -99,16 +114,16 @@ local attributes = {
key = "anchoroffsetx",
label = "Anchor X Offset",
widget = "range",
minvalue = -20,
maxvalue = 20,
minvalue = -120,
maxvalue = 120,
setter = function(widget, value) detailsFramework:SetAnchor(widget, value, widget:GetParent()) end
},
{
key = "anchoroffsety",
label = "Anchor Y Offset",
widget = "range",
minvalue = -20,
maxvalue = 20,
minvalue = -120,
maxvalue = 120,
setter = function(widget, value) detailsFramework:SetAnchor(widget, value, widget:GetParent()) end
},
},
@@ -196,16 +211,16 @@ local attributes = {
key = "anchoroffsetx",
label = "Anchor X Offset",
widget = "range",
minvalue = -20,
maxvalue = 20,
minvalue = -120,
maxvalue = 120,
setter = function(widget, value) detailsFramework:SetAnchor(widget, value, widget:GetParent()) end
},
{
key = "anchoroffsety",
label = "Anchor Y Offset",
widget = "range",
minvalue = -20,
maxvalue = 20,
minvalue = -120,
maxvalue = 120,
setter = function(widget, value) detailsFramework:SetAnchor(widget, value, widget:GetParent()) end
},
{
@@ -232,21 +247,23 @@ local attributes = {
---@class df_editormixin : table
---@field GetAllRegisteredObjects fun(self:df_editor):df_editor_objectinfo[]
---@field GetEditingObject fun(self:df_editor):uiobject
---@field GetEditingObjectIndex fun(self:df_editor):number?
---@field GetEditingOptions fun(self:df_editor):df_editobjectoptions
---@field GetExtraOptions fun(self:df_editor):table
---@field GetEditingProfile fun(self:df_editor):table, table
---@field GetOnEditCallback fun(self:df_editor):function
---@field GetOptionsFrame fun(self:df_editor):frame
---@field GetOptionsFrame fun(self:df_editor):df_menu
---@field GetCanvasScrollBox fun(self:df_editor):df_canvasscrollbox
---@field GetObjectSelector fun(self:df_editor):df_scrollbox
---@field EditObject fun(self:df_editor, object:uiobject, profileTable:table?, profileKeyMap:table?, extraOptions:table?, callback:function?, options:df_editobjectoptions?)
---@field PrepareObjectForEditing fun(self:df_editor)
---@field CreateMoverGuideLines fun(self:df_editor)
---@field GetOverTheTopFrame fun(self:df_editor):frame
---@field GetMoverFrame fun(self:df_editor):frame
---@field CreateMoverFrames fun(self:df_editor):df_editor_mover[]
---@field GetMoverFrames fun(self:df_editor):df_editor_move
---@field StartObjectMovement fun(self:df_editor, anchorSettings:df_anchor)
---@field StopObjectMovement fun(self:df_editor)
---@field RegisterObject fun(self:df_editor, object:uiobject, localizedLabel:string, id:any, profileTable:table, subTablePath:string, profileKeyMap:table, extraOptions:table?, callback:function?, options:df_editobjectoptions?):df_editor_objectinfo
---@field RegisterObject fun(self:df_editor, object:uiobject, localizedLabel:string, id:any, profileTable:table, subTablePath:string, profileKeyMap:table, extraOptions:table?, callback:function?, options:df_editobjectoptions?, refFrame:frame):df_editor_objectinfo
---@field UnregisterObject fun(self:df_editor, object:uiobject)
---@field EditObjectById fun(self:df_editor, id:any)
---@field EditObjectByIndex fun(self:df_editor, index:number)
@@ -254,8 +271,10 @@ local attributes = {
---@field GetObjectByRef fun(self:df_editor, object:uiobject):df_editor_objectinfo
---@field GetObjectByIndex fun(self:df_editor, index:number):df_editor_objectinfo
---@field GetObjectById fun(self:df_editor, id:any):df_editor_objectinfo
---@field GetEditingRegisteredObject fun(self:df_editor):df_editor_objectinfo
---@field CreateObjectSelectionList fun(self:df_editor, scroll_width:number, scroll_height:number, scroll_lines:number, scroll_line_height:number):df_scrollbox
---@field OnHide fun(self:df_editor)
---@field OnShow fun(self:df_editor)
---@field UpdateProfileTableOnAllRegisteredObjects fun(self:df_editor, profileTable:table)
---@field GetProfileTableFromObject fun(self:df_editor, object:df_editor_objectinfo):table
@@ -273,6 +292,7 @@ local editObjectDefaultOptions = {
text_template = detailsFramework:GetTemplate("font", "OPTIONS_FONT_TEMPLATE"),
}
local getParentTable = function(profileTable, profileKey)
local parentPath
if (profileKey:match("%]$")) then
@@ -291,6 +311,18 @@ detailsFramework.EditorMixin = {
return self.editingObject
end,
---@param self df_editor
GetEditingObjectIndex = function(self)
local object = self:GetEditingObject()
local registeredObjects = self:GetAllRegisteredObjects()
for i = 1, #registeredObjects do
local objectRegistered = registeredObjects[i]
if (objectRegistered.object == object) then
return i
end
end
end,
---@param self df_editor
---@return df_editobjectoptions
GetEditingOptions = function(self)
@@ -323,8 +355,8 @@ detailsFramework.EditorMixin = {
return self.overTheTopFrame
end,
GetMoverFrame = function(self)
return self.moverFrame
GetMoverFrames = function(self)
return self.moverFrames
end,
GetCanvasScrollBox = function(self)
@@ -335,60 +367,9 @@ detailsFramework.EditorMixin = {
return self.objectSelector
end,
EditObjectById = function(self, id)
---@type df_editor_objectinfo
local objectRegistered = self:GetObjectById(id)
assert(type(objectRegistered) == "table", "EditObjectById() object not found.")
self:EditObject(objectRegistered)
self.objectSelector:RefreshMe()
end,
EditObjectByIndex = function(self, index)
---@type df_editor_objectinfo
local objectRegistered = self:GetObjectByIndex(index)
assert(type(objectRegistered) == "table", "EditObjectById() object not found.")
self:EditObject(objectRegistered)
self.objectSelector:RefreshMe()
end,
---@param self df_editor
---@param registeredObject df_editor_objectinfo
EditObject = function(self, registeredObject)
--clear previous values
self.editingObject = nil
self.editingProfileMap = nil
self.editingProfileTable = nil
self.editingOptions = nil
self.editingExtraOptions = nil
self.onEditCallback = nil
local object = registeredObject.object
local profileKeyMap = registeredObject.profilekeymap
local extraOptions = registeredObject.extraoptions
local callback = registeredObject.callback
local options = registeredObject.options
local profileTable = self:GetProfileTableFromObject(registeredObject)
assert(type(profileTable) == "table", "EditObject() profileTable is invalid.")
--as there's no other place which this members are set, there is no need to create setter functions
self.editingObject = object
self.editingProfileMap = profileKeyMap
self.editingProfileTable = profileTable
self.editingOptions = options
self.editingExtraOptions = extraOptions
if (type(callback) == "function") then
self.onEditCallback = callback
end
self:PrepareObjectForEditing()
end,
---@param self df_editor
CreateMoverGuideLines = function(self)
local overTheTopFrame = self:GetOverTheTopFrame()
local moverFrame = self:GetMoverFrame()
self.moverGuideLines = {
left = overTheTopFrame:CreateTexture(nil, "overlay"),
@@ -434,12 +415,326 @@ detailsFramework.EditorMixin = {
end
end,
--screen position offset is the XY screen position offset from the bottom left of the screen, they are always positive, they go from 0 to screen width or height
CreateAnchorFrames = function(editorFrame)
--table containing 9 buttons, each one in a different position of the object, indexes one to nine in this order: topleft, left, bottomleft, bottom, bottomright, right, topright, top, center
editorFrame.AnchorFrames = {
anchorFrames = {},
DisableAllAnchors = function(self)
for i = 1, 9 do
local anchorFrame = self:GetAnchorFrame(i)
self:SetNotInUse(anchorFrame)
anchorFrame:Hide()
end
end,
SetupAnchorsForObject = function(self, object, anchorTable)
editorFrame.AnchorFrames:DisableAllAnchors()
local registeredObject = editorFrame:GetEditingRegisteredObject()
if (registeredObject.refFrame) then
for i = 1, 9 do
local anchorFrame = self.anchorFrames[i]
local anchorName = detailsFramework.AnchorPointsByIndex[i]
anchorFrame:ClearAllPoints()
anchorFrame:SetPoint(anchorName, registeredObject.refFrame, anchorName, 0, 0)
anchorFrame:Show()
end
local sideSelected = anchorTable.side
local anchorFrameSelected = self:GetAnchorFrame(detailsFramework.InsidePointsToAnchor[sideSelected] or sideSelected)
self:SetInUse(anchorFrameSelected)
self.anchorTable = anchorTable
end
end,
--when the user click on one of the anchor points, change the anchor side setting and recalculate the xy offset of the new point related to the same point in the object
SelectAnchorPoint = function(anchorFrame)
editorFrame.AnchorFrames:SetNotInUseForAllAnchors()
--change the color of the anchor point to show it's selected
anchorFrame.Texture:SetColorTexture(1, 0, 0, 0.5)
--get the object being edited in the editor
local object = editorFrame:GetEditingObject()
--get the xy of the nine points of the object
local ninePoints = detailsFramework.Math.GetNinePoints(object)
--get the coordinates of the anchorIndex within the ninePoints table
--the xy point in here is the XY screen position offset from the bottom left of the screen
local screenPoint = ninePoints[anchorFrame.anchorIndex]
local objectScreenPosX = screenPoint.x
local objectScreenPosY = screenPoint.y
--get the screen position offset of the anchor
local anchorScreenPosX, anchorScreenPosY = anchorFrame:GetCenter()
--calculate the xy offset of the anchor point related to the object
local offsetX = objectScreenPosX - anchorScreenPosX
local offsetY = objectScreenPosY - anchorScreenPosY
--get the anchor settings table
local anchorTable = editorFrame.AnchorFrames.anchorTable
--set the anchor settings
anchorTable.x = offsetX
anchorTable.y = offsetY
anchorTable.side = detailsFramework.AnchorPointsToInside[anchorFrame.anchorIndex]
C_Timer.After(0, function()
editorFrame:PrepareObjectForEditing()
end)
end,
GetAnchorFrame = function(self, anchorIndex)
return self.anchorFrames[anchorIndex]
end,
SetNotInUseForAllAnchors = function(self)
for i = 1, 9 do
local anchorFrame = self:GetAnchorFrame(i)
self:SetNotInUse(anchorFrame)
end
end,
SetNotInUse = function(self, anchorFrame)
anchorFrame.Texture:SetColorTexture(1, 1, 1, 0.5)
end,
SetInUse = function(self, anchorFrame)
anchorFrame.Texture:SetColorTexture(1, 0, 0, 0.5)
end,
CreateNineAnchors = function(self)
local overTheTopFrame = editorFrame:GetOverTheTopFrame()
for i = 1, 9 do
local anchorFrame = CreateFrame("button", "$parentAnchorFrame" .. i, overTheTopFrame, "BackdropTemplate")
anchorFrame:SetSize(8, 8)
anchorFrame:SetBackdrop({bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true})
anchorFrame:SetBackdropColor(1, 0, 0, 0.5)
anchorFrame:SetFrameStrata("TOOLTIP")
anchorFrame:SetFrameLevel(10)
anchorFrame.anchorIndex = i
anchorFrame:Hide()
anchorFrame:SetScript("OnClick", editorFrame.AnchorFrames.SelectAnchorPoint)
self.anchorFrames[i] = anchorFrame
anchorFrame.Texture = anchorFrame:CreateTexture("$parentTexture", "border")
anchorFrame.Texture:SetColorTexture(1, 1, 1, 0.5)
anchorFrame.Texture:SetAllPoints(anchorFrame)
end
end,
}
editorFrame.AnchorFrames:CreateNineAnchors()
return editorFrame.AnchorFrames
end,
---create a frame to move the object, the frame is attached into the bottom right of the selected object
---@param editorFrame df_editor
---@return df_editor_movermain
CreateMoverFrames = function(editorFrame)
local amountOfMovers = 1
--frame that is used to move the object
---@type df_editor_movermain
local movers = {
anchorNames = {"bottomright", "bottomleft", "topright", "topleft"},
Hide = function(self)
for i = 1, amountOfMovers do
self[i]:Hide()
end
end,
Stop = function(self)
self.bIsMoving = false
for i = 1, amountOfMovers do
local moverFrame = self[i]
moverFrame:StopMovingOrSizing()
moverFrame:SetScript("OnUpdate", nil)
end
end,
UpdatePosition = function(self, moverFrame)
for i = 1, amountOfMovers do
local thisMoverFrame = self[i]
if (thisMoverFrame ~= moverFrame) then
thisMoverFrame.OnTickNotMoving(thisMoverFrame, 0)
end
end
end,
Setup = function(self, object, registeredObject, onTickWhileMoving, onTickNotMoving)
for i = 1, amountOfMovers do
local moverFrame = self[i]
moverFrame:Show()
moverFrame:EnableMouse(true)
moverFrame.OnTickWhileMoving = onTickWhileMoving
moverFrame.OnTickNotMoving = onTickNotMoving
moverFrame.anchorName = self.anchorNames[i]
moverFrame:SetScript("OnMouseDown", function()
--save the current position of the object
local startX, startY = moverFrame:GetCenter()
moverFrame.MovingInfo.startX = startX
moverFrame.MovingInfo.startY = startY
editorFrame.currentObjectNinePoints = detailsFramework.Math.GetNinePoints(registeredObject.refFrame)
--start moving
moverFrame:SetScript("OnUpdate", onTickWhileMoving)
moverFrame.bIsMoving = true
moverFrame:StartMoving()
end)
moverFrame:SetScript("OnMouseUp", function()
self:Stop()
moverFrame:EnableMouse(true)
--save the current position of the object selected
local x, y = object:GetCenter()
moverFrame.MovingInfo.restingX = x
moverFrame.MovingInfo.restingY = y
moverFrame:SetScript("OnUpdate", onTickNotMoving)
local currentNinePoints = editorFrame.currentObjectNinePoints
local startX, startY = moverFrame:GetCenter()
local closestPoint = editorFrame.currentObjectNinePoints:GetClosestPoint(CreateVector2D(startX, startY))
--if (closestPoint ~= parentTable.side) then
--print("side is different", closestPoint, parentTable.side)
--end
end)
moverFrame:ClearAllPoints()
if (i == 1) then
if (amountOfMovers == 1) then
moverFrame:SetPoint("topleft", object, "topleft", 0, 0)
moverFrame:SetPoint("bottomright", object, "bottomright", 0, 0)
else
moverFrame:SetPoint("center", object, "bottomright", 0, 0)
end
elseif (i == 2) then
moverFrame:SetPoint("center", object, "bottomleft", 0, 0)
elseif (i == 3) then
moverFrame:SetPoint("center", object, "topright", 0, 0)
elseif (i == 4) then
moverFrame:SetPoint("center", object, "topleft", 0, 0)
moverFrame:SetSize(object:GetWidth(), object:GetHeight())
end
local x, y = moverFrame:GetCenter()
moverFrame:SetPoint("center", UIParent, "bottomleft", x, y)
--current position of object selected
local x, y = object:GetCenter()
moverFrame.MovingInfo.restingX = x
moverFrame.MovingInfo.restingY = y
moverFrame:SetScript("OnUpdate", onTickNotMoving)
end
self.ObjectBackgroundTexture:SetPoint("topleft", object, "topleft", 0, 0)
self.ObjectBackgroundTexture:SetSize(object:GetWidth(), object:GetHeight())
end,
}
for i = 1, amountOfMovers do
---@type df_editor_mover
local moverFrame = CreateFrame("button", "$parentMover" .. i, UIParent, "BackdropTemplate")
moverFrame:SetFrameStrata("TOOLTIP")
moverFrame:SetSize(16, 16)
moverFrame:SetClampedToScreen(true)
moverFrame:EnableMouse(true)
moverFrame:SetMovable(true)
moverFrame:SetFrameLevel(math.abs(i-5))
moverFrame.MovingInfo = {
startX = 0,
startY = 0,
restingX = 0,
restingY = 0,
}
movers[i] = moverFrame
moverFrame.MoverIcon = moverFrame:CreateTexture("$parentMoverIcon", "overlay")
moverFrame.MoverIcon:SetTexture([[Interface\CHATFRAME\CHATFRAMEBACKGROUND]])
moverFrame.MoverIcon:SetSize(6, 6)
moverFrame.MoverIcon:SetPoint("center", moverFrame, "center", 0, 0)
end
movers.ObjectBackgroundTexture = movers[1]:CreateTexture("$parentMoverObjectBackground", "artwork")
movers.ObjectBackgroundTexture:SetColorTexture(1, 1, 1, 0.25)
return movers
end,
EditObjectById = function(self, id)
---@type df_editor_objectinfo
local objectRegistered = self:GetObjectById(id)
assert(type(objectRegistered) == "table", "EditObjectById() object not found.")
self:EditObject(objectRegistered)
self.objectSelector:RefreshMe()
end,
EditObjectByIndex = function(self, index)
---@type df_editor_objectinfo
local objectRegistered = self:GetObjectByIndex(index)
assert(type(objectRegistered) == "table", "EditObjectById() object not found.")
self:EditObject(objectRegistered)
self.objectSelector:RefreshMe()
end,
---@param self df_editor
---@param registeredObject df_editor_objectinfo
EditObject = function(self, registeredObject)
--clear previous values
self.editingObject = nil
self.editingProfileMap = nil
self.editingProfileTable = nil
self.editingOptions = nil
self.editingExtraOptions = nil
self.onEditCallback = nil
local object = registeredObject.object
local profileKeyMap = registeredObject.profilekeymap
local extraOptions = registeredObject.extraoptions
local callback = registeredObject.callback
local options = registeredObject.options
local profileTable = self:GetProfileTableFromObject(registeredObject)
assert(type(profileTable) == "table", "EditObject() profileTable is invalid.")
--as there's no other place which this members are set, there is no need to create setter functions
self.registeredObjectInfo = registeredObject
self.editingObject = object
self.editingProfileMap = profileKeyMap
self.editingProfileTable = profileTable
self.editingOptions = options
self.editingExtraOptions = extraOptions
if (type(callback) == "function") then
self.onEditCallback = callback
end
self:PrepareObjectForEditing()
end,
PrepareObjectForEditing = function(self) --~edit
--get the object and its profile table with the current values
local object = self:GetEditingObject()
local profileTable, profileMap = self:GetEditingProfile()
profileMap = profileMap or {}
self.AnchorFrames:DisableAllAnchors()
local conditionalKeys = profileMap.enable_if or {}
if (not object or not profileTable) then
@@ -502,8 +797,6 @@ detailsFramework.EditorMixin = {
value = profileTable[profileKey]
end
--print(value, profileKey, profileTable, option.key)
--if no value is found, attempt to get a default
if (type(value) == "nil") then
value = option.default
@@ -515,11 +808,11 @@ detailsFramework.EditorMixin = {
local maxValue = option.maxvalue
if (option.key == "anchoroffsetx") then
minValue = -math.floor(object:GetParent():GetWidth()/10)
maxValue = math.floor(object:GetParent():GetWidth()/10)
minValue = -math.floor(object:GetParent():GetWidth())
maxValue = math.floor(object:GetParent():GetWidth())
elseif (option.key == "anchoroffsety") then
minValue = -math.floor(object:GetParent():GetHeight()/10)
maxValue = math.floor(object:GetParent():GetHeight()/10)
minValue = -math.floor(object:GetParent():GetHeight())
maxValue = math.floor(object:GetParent():GetHeight())
end
if (bHasValue) then
@@ -586,7 +879,6 @@ detailsFramework.EditorMixin = {
id = option.key,
}
--disabled = true
if (conditionalKeys[option.key]) then
local bIsEnabled = conditionalKeys[option.key](object, profileTable, profileKey)
if (not bIsEnabled) then
@@ -599,6 +891,10 @@ detailsFramework.EditorMixin = {
end
end
if (anchorSettings) then
self.AnchorFrames:SetupAnchorsForObject(object, anchorSettings)
end
--at this point, the optionsTable is ready to be used on DF:BuildMenuVolatile()
menuOptions.align_as_pairs = true
menuOptions.align_as_pairs_length = 150
@@ -637,12 +933,6 @@ detailsFramework.EditorMixin = {
StartObjectMovement = function(self, anchorSettings)
local object = self:GetEditingObject()
local moverFrame = self:GetMoverFrame()
moverFrame:EnableMouse(true)
moverFrame:SetMovable(true)
moverFrame:ClearAllPoints()
moverFrame:Show()
--update guidelines
if (self:GetEditingOptions().use_guide_lines) then
--self:UpdateGuideLinesAnchors()
@@ -652,117 +942,75 @@ detailsFramework.EditorMixin = {
end
end
local registeredObject = self:GetEditingRegisteredObject()
local optionsFrame = self:GetOptionsFrame()
local objectParent = object:GetParent()
local moverFrames = self:GetMoverFrames()
--getting the size this way due to the cascade of different scales that are applyed to unitFrame objects
moverFrame:ClearAllPoints()
moverFrame:SetPoint("topleft", object, "topleft", -5, 5)
moverFrame:SetPoint("bottomright", object, "bottomright", 5, -5)
local moverWidth, moverHeight = moverFrame:GetSize()
local onTickWhileMoving = function(moverFrame, deltaTime)
local startX, startY = moverFrame:GetCenter()
local xOffset = startX - moverFrame.MovingInfo.startX
local yOffset = startY - moverFrame.MovingInfo.startY
local objectWidth, objectHeight = object:GetSize()
moverFrame:SetSize(moverWidth, moverHeight)
detailsFramework:SetAnchor(moverFrame, anchorSettings, object:GetParent())
local currentPosX, currentPosY
if (xOffset ~= 0 or yOffset ~= 0) then
moverFrame.MovingInfo.startX = startX
moverFrame.MovingInfo.startY = startY
anchorSettings.x = anchorSettings.x + xOffset
anchorSettings.y = anchorSettings.y + yOffset
detailsFramework:SetAnchor(object, anchorSettings, objectParent)
moverFrame:SetScript("OnMouseDown", function()
object:ClearAllPoints()
object:SetPoint("topleft", moverFrame, "topleft", 0, 0)
--update the slider offset in the options frame
local anchorXSlider = optionsFrame:GetWidgetById("anchoroffsetx")
anchorXSlider:SetValueNoCallback(anchorSettings.x)
local anchorYSlider = optionsFrame:GetWidgetById("anchoroffsety")
anchorYSlider:SetValueNoCallback(anchorSettings.y)
currentPosX, currentPosY = moverFrame:GetCenter()
moverFrame.bIsMoving = true
moverFrame:StartMoving()
end)
--save the new position
local profileTable, profileMap = self:GetEditingProfile()
local profileKey = profileMap.anchor
local parentTable = getParentTable(profileTable, profileKey)
parentTable.x = anchorSettings.x
parentTable.y = anchorSettings.y
moverFrame:SetScript("OnMouseUp", function()
moverFrame:StopMovingOrSizing()
moverFrame.bIsMoving = false
--0.64 UIParent
--0.96 object
--local scale = object:GetEffectiveScale() / UIParent:GetEffectiveScale() --1.5
local originX = anchorSettings.x
local originY = anchorSettings.y
local newPosX, newPosY = moverFrame:GetCenter()
local xOffset = newPosX - currentPosX
local yOffset = newPosY - currentPosY
xOffset = xOffset
yOffset = yOffset
anchorSettings.x = (originX + xOffset)
anchorSettings.y = (originY + yOffset)
local anchorXSlider = optionsFrame:GetWidgetById("anchoroffsetx")
anchorXSlider:SetValueNoCallback(anchorSettings.x)
local anchorYSlider = optionsFrame:GetWidgetById("anchoroffsety")
anchorYSlider:SetValueNoCallback(anchorSettings.y)
object:ClearAllPoints()
detailsFramework:SetAnchor(object, anchorSettings, object:GetParent())
--save the new position
local profileTable, profileMap = self:GetEditingProfile()
local profileKey = profileMap.anchor
local parentTable = getParentTable(profileTable, profileKey)
parentTable.x = anchorSettings.x
parentTable.y = anchorSettings.y
if (self:GetOnEditCallback()) then
self:GetOnEditCallback()(object, "x", anchorSettings.x, profileTable, profileKey)
self:GetOnEditCallback()(object, "y", anchorSettings.x, profileTable, profileKey)
end
end)
--detailsFramework:SetAnchor(moverFrame, anchorSettings)
--detailsFramework:SetAnchor(object, anchorSettings, moverFrame)
moverFrame:SetScript("OnUpdate", function() --not in use
--if the object isn't moving, make the mover follow the object position
if (false and moverFrame.bIsMoving) then
--object:ClearAllPoints()
--object:SetPoint("topleft", moverFrame, "topleft", 0, 0)
--if the object is moving, check if the moverFrame has moved
local newPosX, newPosY = moverFrame:GetCenter()
--did the frame moved?
if (newPosX ~= currentPosX) then
local xOffset = newPosX - currentPosX
anchorSettings.x = anchorSettings.x + xOffset
local anchorXSlider = optionsFrame:GetWidgetById("anchoroffsetx")
anchorXSlider:SetValueNoCallback(anchorSettings.x)
local closestPoint = self.currentObjectNinePoints:GetClosestPoint(CreateVector2D(startX, startY))
if (closestPoint ~= parentTable.side) then
--print("side is different", closestPoint, parentTable.side)
end
if (newPosY ~= currentPosY) then
local yOffset = newPosY - currentPosY
anchorSettings.y = anchorSettings.y + yOffset
local anchorYSlider = optionsFrame:GetWidgetById("anchoroffsety")
anchorYSlider:SetValueNoCallback(anchorSettings.y)
if (self:GetOnEditCallback()) then
self:GetOnEditCallback()(object, "x", anchorSettings.x, profileTable, profileKey)
self:GetOnEditCallback()(object, "y", anchorSettings.y, profileTable, profileKey)
end
currentPosX, currentPosY = newPosX, newPosY
moverFrames:UpdatePosition(moverFrame)
end
end)
end
local onTickNotMoving = function(moverFrame, deltaTime)
--current position of the selected object
local objectX, objectY = object:GetCenter()
--did the object move?
if (objectX ~= moverFrame.MovingInfo.restingX or objectY ~= moverFrame.MovingInfo.restingY) then
moverFrame:SetPoint("center", object, moverFrame.anchorName, 0, 0)
local x, y = moverFrame:GetCenter()
moverFrame:SetPoint("center", UIParent, "bottomleft", x, y)
moverFrame.MovingInfo.restingX = objectX
moverFrame.MovingInfo.restingY = objectY
end
end
moverFrames:Setup(object, registeredObject, onTickWhileMoving, onTickNotMoving)
end,
---@param self df_editor
StopObjectMovement = function(self)
local moverFrame = self:GetMoverFrame()
moverFrame:EnableMouse(false)
moverFrame:SetScript("OnUpdate", nil)
local moverFrame = self:GetMoverFrames()
moverFrame:Stop()
--hide all four guidelines
for side, texture in pairs(self.moverGuideLines) do
texture:Hide()
end
moverFrame:Hide()
end,
---@param self df_editor
@@ -794,7 +1042,7 @@ detailsFramework.EditorMixin = {
objectSelector:RefreshMe()
end,
RegisterObject = function(self, object, localizedLabel, id, profileTable, subTablePath, profileKeyMap, extraOptions, callback, options)
RegisterObject = function(self, object, localizedLabel, id, profileTable, subTablePath, profileKeyMap, extraOptions, callback, options, refFrame)
assert(type(object) == "table", "RegisterObjectToEdit() expects an UIObject on #1 parameter.")
assert(object.GetObjectType, "RegisterObjectToEdit() expects an UIObject on #1 parameter.")
assert(type(profileTable) == "table", "RegisterObjectToEdit() expects a table on #4 parameter.")
@@ -833,18 +1081,20 @@ detailsFramework.EditorMixin = {
callback = callback,
options = options,
selectButton = selectButton,
refFrame = refFrame,
}
selectButton:SetScript("OnClick", function()
self:EditObject(objectRegistered)
end)
registeredObjects[#registeredObjects+1] = objectRegistered
self.registeredObjectsByID[id] = objectRegistered
local objectSelector = self:GetObjectSelector()
objectSelector:RefreshMe()
selectButton:SetScript("OnClick", function()
self:EditObject(objectRegistered)
objectSelector:RefreshMe()
end)
--what to do after an object is registered?
return objectRegistered
end,
@@ -885,6 +1135,13 @@ detailsFramework.EditorMixin = {
end
end,
---@param self df_editor
---@return df_editor_objectinfo
GetEditingRegisteredObject = function(self)
return self.registeredObjectInfo
end,
GetObjectByIndex = function(self, index)
local registeredObjects = self:GetAllRegisteredObjects()
return registeredObjects[index]
@@ -987,6 +1244,18 @@ detailsFramework.EditorMixin = {
OnHide = function(self)
self:StopObjectMovement()
local moverFrames = self:GetMoverFrames()
moverFrames:Hide()
end,
---@param self df_editor
OnShow = function(self)
--get the editing object
local objectIndex = self:GetEditingObjectIndex()
if (objectIndex) then
self:EditObjectByIndex(objectIndex)
self.objectSelector:RefreshMe()
end
end,
}
@@ -1023,6 +1292,7 @@ function detailsFramework:CreateEditor(parent, name, options)
detailsFramework:Mixin(editorFrame, detailsFramework.EditorMixin)
detailsFramework:Mixin(editorFrame, detailsFramework.OptionsFunctions)
editorFrame:SetScript("OnShow", editorFrame.OnShow)
editorFrame:SetScript("OnHide", editorFrame.OnHide)
editorFrame.registeredObjects = {}
@@ -1033,6 +1303,7 @@ function detailsFramework:CreateEditor(parent, name, options)
editorFrame:SetSize(editorFrame.options.width, editorFrame.options.height)
--The options frame holds the options for the object being edited. It is used as the parent frame for the BuildMenuVolatile() function.
---@type df_menu
local optionsFrame = CreateFrame("frame", name .. "OptionsFrame", editorFrame, "BackdropTemplate")
optionsFrame:SetSize(editorFrame.options.options_width, 5000)
@@ -1068,14 +1339,9 @@ function detailsFramework:CreateEditor(parent, name, options)
OTTFrame:SetFrameStrata("TOOLTIP")
editorFrame.overTheTopFrame = OTTFrame
--frame that is used to move the object
local moverFrame = CreateFrame("frame", "$parentMoverFrame", OTTFrame, "BackdropTemplate")
moverFrame:SetClampedToScreen(true)
detailsFramework:ApplyStandardBackdrop(moverFrame)
moverFrame:SetBackdropColor(.10, .10, .10, 0)
moverFrame.__background:SetAlpha(0.1)
editorFrame.moverFrame = moverFrame
editorFrame:CreateAnchorFrames()
editorFrame.moverFrames = editorFrame:CreateMoverFrames()
editorFrame:CreateMoverGuideLines()
editorFrame.optionsFrame = optionsFrame
+117 -10
View File
@@ -1,6 +1,6 @@
local dversion = 532
local dversion = 534
local major, minor = "DetailsFramework-1.0", dversion
local DF, oldminor = LibStub:NewLibrary(major, minor)
@@ -2038,6 +2038,7 @@ end
---@field x number
---@field y number
DF.AnchorPoints = {
"Top Left",
"Left",
@@ -2047,17 +2048,123 @@ DF.AnchorPoints = {
"Right",
"Top Right",
"Top",
"Center",
"Inside Left",
"Inside Right",
"Inside Top",
"Inside Bottom",
"Inside Top Left",
"Inside Bottom Left",
"Inside Bottom Right",
"Inside Top Right",
"Center", --9
"Inside Left", --10
"Inside Right", --11
"Inside Top", --12
"Inside Bottom", --13
"Inside Top Left", --14
"Inside Bottom Left", --15
"Inside Bottom Right", --16
"Inside Top Right", --17
}
DF.AnchorPointsByIndex = {
"topleft", --1
"left", --2
"bottomleft", --3
"bottom", --4
"bottomright", --5
"right", --6
"topright", --7
"top", --8
"center", --9
}
DF.AnchorPointsToInside = {
[9] = 9,
[8] = 12,
[7] = 17,
[6] = 11,
[5] = 16,
[4] = 13,
[3] = 15,
[2] = 10,
[1] = 14,
}
DF.InsidePointsToAnchor = {
[9] = 9,
[12] = 8,
[17] = 7,
[11] = 6,
[16] = 5,
[13] = 4,
[15] = 3,
[10] = 2,
[14] = 1,
}
function DF:ConvertAnchorPointToInside(anchorPoint)
return DF.AnchorPointsToInside[anchorPoint] or anchorPoint
end
local calcPointCoords = function(ninePointsWidget, ninePointsRef, anchorTable, coordIndex, newAnchorSide)
--get the location of the topleft corner relative to the bottomleft corner of the screen
---@type df_coordinate
local widgetPointCoords = ninePointsWidget[coordIndex]
--get the topleft coords of the reference widget
---@type df_coordinate
local refPointCoords = ninePointsRef[coordIndex]
--calculate the offset of the x and y axis
local x = refPointCoords.x - widgetPointCoords.x
local y = refPointCoords.y - widgetPointCoords.y
anchorTable.x = x
anchorTable.y = y
anchorTable.side = newAnchorSide
print("new anchor side", newAnchorSide, "x", x, "y", y)
end
function DF:ConvertAnchorOffsets(widget, referenceWidget, anchorTable, newAnchorSide)
if (anchorTable.side == newAnchorSide) then
return anchorTable
end
local ninePoints = DF.Math.GetNinePoints(widget)
local refNinePoints = DF.Math.GetNinePoints(referenceWidget)
--the numeration from 1 to 9 is the index within a ninePoints table
anchorTable.side = newAnchorSide
if (newAnchorSide == 14) then --inside topleft
anchorTable.x = ninePoints[1].x - refNinePoints[1].x
anchorTable.y = ninePoints[1].y - refNinePoints[1].y
--print("inside topleft", anchorTable.x, anchorTable.y)
elseif (newAnchorSide == 15) then --inside bottomleft
anchorTable.x = ninePoints[3].x - refNinePoints[3].x
anchorTable.y = ninePoints[3].y - refNinePoints[3].y
elseif (newAnchorSide == 16) then --inside bottomright
anchorTable.x = refNinePoints[5].x - ninePoints[5].x
anchorTable.y = refNinePoints[5].y - ninePoints[5].y
elseif (newAnchorSide == 17) then --inside topright
anchorTable.x = refNinePoints[7].x - ninePoints[7].x
anchorTable.y = refNinePoints[7].y - ninePoints[7].y
elseif (newAnchorSide == 10) then --inside left
calcPointCoords(ninePoints, refNinePoints, anchorTable, 2, newAnchorSide)
elseif (newAnchorSide == 11) then --inside right
calcPointCoords(ninePoints, refNinePoints, anchorTable, 6, newAnchorSide)
elseif (newAnchorSide == 12) then --inside top
calcPointCoords(ninePoints, refNinePoints, anchorTable, 8, newAnchorSide)
elseif (newAnchorSide == 13) then --inside bottom
calcPointCoords(ninePoints, refNinePoints, anchorTable, 4, newAnchorSide)
elseif (newAnchorSide == 9) then --center
calcPointCoords(ninePoints, refNinePoints, anchorTable, 9, newAnchorSide)
else
--print("not implemented")
end
end
local anchoringFunctions = {
function(frame, anchorTo, offSetX, offSetY) --1 TOP LEFT
frame:ClearAllPoints()
+81
View File
@@ -40,6 +40,87 @@ DF.Math = {}
---@field MultiplyBy fun(value: number, ...) : ... multiply all the passed values by value.
---@field MapRangeColor fun(inputX: number, inputY: number, outputX: number, outputY: number, red: number, green: number, blue: number) : number, number, number
---@field RandomFraction fun(minValue: number, maxValue: number) : number
---@field GetNinePoints fun(object: uiobject) : df_ninepoints
---@field GetClosestPoint fun(ninePoints: df_ninepoints, coordinate: df_coordinate) : anchorid
---@class df_coordinate : table
---@field x number
---@field y number
---@class df_ninepoints : df_coordinate[]
---@field GetClosestPoint fun(ninePoints: df_ninepoints, coordinate: df_coordinate) : anchorid
---this function receives a df_ninepoints and a df_coordinate, iterates among the points and return the closest point to the given coordinate
---@param ninePoints df_ninepoints
---@param coordinate df_coordinate
---@return anchorid, number, number, number, number
function DF.Math.GetClosestPoint(ninePoints, coordinate)
local closestPoint = 1
local closestDistance = DF.Math.GetPointDistance(ninePoints[1].x, ninePoints[1].y, coordinate.x, coordinate.y)
--get the x and y offset from the closest point to the given coordinate
local offsetX = coordinate.x - ninePoints[1].x
local offsetY = coordinate.y - ninePoints[1].y
for i = 2, #ninePoints do
local distance = DF.Math.GetPointDistance(ninePoints[i].x, ninePoints[i].y, coordinate.x, coordinate.y)
if (distance < closestDistance) then
closestDistance = distance
closestPoint = i
--updade the offset
offsetX = coordinate.x - ninePoints[i].x
offsetY = coordinate.y - ninePoints[i].y
end
end
return closestPoint, offsetX, offsetY, ninePoints[closestPoint].x, ninePoints[closestPoint].y
end
---this function receives an object and get the location of the topleft, left, bottomleft, bottom, bottomright, right, topright, top and center points
---return a table with subtables with x and y values for each point
---@param object uiobject
---@return df_ninepoints
function DF.Math.GetNinePoints(object)
local centerX, centerY = object:GetCenter()
local width = object:GetWidth()
local height = object:GetHeight()
local halfWidth = width / 2
local halfHeight = height / 2
---@type df_ninepoints
local ninePoints = {
{x = centerX - halfWidth, y = centerY + halfHeight}, --topleft 1
{x = centerX - halfWidth, y = centerY}, --left 2
{x = centerX - halfWidth, y = centerY - halfHeight}, --bottomleft 3
{x = centerX, y = centerY - halfHeight}, --bottom 4
{x = centerX + halfWidth, y = centerY - halfHeight}, --bottomright 5
{x = centerX + halfWidth, y = centerY}, --right 6
{x = centerX + halfWidth, y = centerY + halfHeight}, --topright 7
{x = centerX, y = centerY + halfHeight}, --top 8
{x = centerX, y = centerY}, --center 9
GetClosestPoint = DF.Math.GetClosestPoint
}
--debug
--[=[
local f = CreateFrame("frame", nil, UIParent)
f:SetFrameStrata("TOOLTIP")
f:SetSize(1, 1)
f:SetPoint("center", UIParent, "center", 0, 0)
for i = 1, #ninePoints do
local point = ninePoints[i]
local t = f:CreateTexture(nil, "overlay")
t:SetColorTexture(1, 0, 0, 1)
t:SetSize(2, 2)
t:SetPoint("bottomleft", UIParent, "bottomleft", point.x, point.y)
end
--]=]
return ninePoints
end
---return a random fraction between two values, example: RandomFraction(.2, .3) returns a number between .2 and .3, 0.25, 0.28, 0.21, etc
function DF.Math.RandomFraction(minValue, maxValue)
+1 -1
View File
@@ -2453,7 +2453,7 @@ function detailsFramework:ShowPromptPanel(message, trueCallback, falseCallback,
if (not DetailsFrameworkPromptSimple) then
local promptFrame = CreateFrame("frame", "DetailsFrameworkPromptSimple", UIParent, "BackdropTemplate")
promptFrame:SetSize(400, 80)
promptFrame:SetFrameStrata("DIALOG")
promptFrame:SetFrameStrata("FULLSCREEN")
promptFrame:SetPoint("center", UIParent, "center", 0, 300)
detailsFramework:ApplyStandardBackdrop(promptFrame)
table.insert(UISpecialFrames, "DetailsFrameworkPromptSimple")