diff --git a/Definitions.lua b/Definitions.lua index 9858759a..a9bebb9e 100644 --- a/Definitions.lua +++ b/Definitions.lua @@ -1,4 +1,11 @@ +--uiobject: is an object that represents a UI element, such as a frame, a texture, or a button. UIObjects are the base class for all UI elements in the WoW API. +--3D World: is an object which is placed behind|below all UI elements, cannot be parent of any object, in the 3D World object is where the game world is rendered +--size: corresponds to the height and height of an object, it is measure in pixels, must be bigger than zero. +--scale: the size of an object is multiplied by this value, it is measure in percentage, must be between 0.65 and 2.40. +--alpha: corresponds to the transparency of an object, the bigger is the value less transparent is the object, it is measure in percentage, must be between 0 and 1, zero is fully transparent and one is fully opaque. + + ---@class _G ---@field RegisterAttributeDriver fun(statedriver: frame, attribute: string, conditional: string) ---@field RegisterStateDriver fun(statedriver: frame, attribute: string, conditional: string) @@ -34,18 +41,19 @@ ---@class unit : string string that represents a unit in the game, such as the player, a party member, or a raid member. ---@class health : number amount of hit points (health) of a unit. This value can be changed by taking damage or healing. ---@class role : string @string(TANK, HEALER, DAMAGER, NONE) is a string that represents the role of a unit, such as tank, healer, or damage dealer. +---@class point : string @string(topleft, topright, bottomleft, bottomright, top, bottom, left, right, center) is a string that represents a point on a frame. Points are used to position frames relative to each other. ---@class uiobject ----@field Show fun(self: uiobject) ----@field Hide fun(self: uiobject) ----@field SetShown fun(self: uiobject, state: boolean) ----@field IsShown fun(self: uiobject) : boolean ----@field SetAllPoints fun(self: uiobject) ----@field SetParent fun(self: uiobject, parent: frame) ----@field SetSize fun(self: uiobject, width: width|number, height: height|number) ----@field SetWidth fun(self: uiobject, width: width|number) ----@field SetHeight fun(self: uiobject, height: height|number) ----@field SetAlpha fun(self: uiobject, alpha: alpha|number) +---@field Show fun(self: uiobject) make the object be shown on the user screen +---@field Hide fun(self: uiobject) make the object be hidden from the user screen +---@field SetShown fun(self: uiobject, state: boolean) show or hide the object +---@field IsShown fun(self: uiobject) : boolean return if the object is shown or not +---@field SetAllPoints fun(self: uiobject) set the object to be the same size as its parent +---@field SetParent fun(self: uiobject, parent: frame) set the parent object of the object +---@field SetSize fun(self: uiobject, width: width|number, height: height|number) set the width and height of the object +---@field SetWidth fun(self: uiobject, width: width|number) set only the width of the object +---@field SetHeight fun(self: uiobject, height: height|number) set only the height of the object +---@field SetAlpha fun(self: uiobject, alpha: alpha|number) set the transparency of the object ---@field SetScale fun(self: uiobject, scale: scale|number) ---@field GetWidth fun(self: uiobject) : width|number ---@field GetHeight fun(self: uiobject) : height|number @@ -54,6 +62,7 @@ ---@field GetSize fun(self: uiobject) : width|number, height|number ---@field GetParent fun(self: uiobject) : frame ---@field GetPoint fun(self: uiobject, index: number): string, frame, string, number, number +---@field GetCenter fun(self: uiobject): number, number ---@field SetPoint fun(self: uiobject, point: "topleft"|"topright"|"bottomleft"|"bottomright"|"top"|"bottom"|"left"|"right"|"center", relativeFrame: uiobject, relativePoint: "topleft"|"topright"|"bottomleft"|"bottomright"|"top"|"bottom"|"left"|"right"|"center", xOffset: number, yOffset: number) ---@field ClearAllPoints fun(self: uiobject) ---@field CreateAnimationGroup fun(self: uiobject, name: string|nil, templateName: string|nil) : animationgroup @@ -134,6 +143,7 @@ ---@field EnableMouse fun(self: frame, enable: boolean) ---@field SetResizable fun(self: frame, enable: boolean) ---@field EnableMouseWheel fun(self: frame, enable: boolean) +---@field RegisterForDrag fun(self: frame, button: string) ---@field SetResizeBounds fun(self: frame, minWidth: number, minHeight: number, maxWidth: number, maxHeight: number) ---@class button : frame @@ -156,6 +166,10 @@ ---@field SetButtonState fun(self: button, state: string, enable: boolean) ---@field GetButtonState fun(self: button, state: string) : boolean ---@field RegisterForClicks fun(self: button, button1: nil|"AnyUp"|"AnyDown"|"LeftButtonDown"|"LeftButtonUp"|"MiddleButtonUp"|"MiddleButtonDown"|"RightButtonDown"|"RightButtonUp"|"Button4Up"|"Button4Down"|"Button5Up"|"Button5Down", button2: nil|"AnyUp"|"AnyDown"|"LeftButtonDown"|"LeftButtonUp"|"MiddleButtonUp"|"MiddleButtonDown"|"RightButtonDown"|"RightButtonUp"|"Button4Up"|"Button4Down"|"Button5Up"|"Button5Down") +---@field GetNormalTexture fun(self: button) : texture +---@field GetPushedTexture fun(self: button) : texture +---@field GetHighlightTexture fun(self: button) : texture +---@field GetDisabledTexture fun(self: button) : texture ---@class statusbar : frame ---@field SetStatusBarColor fun(self: statusbar, r: red|number, g: green|number, b: blue|number, a: alpha|number) diff --git a/Libs/DF/containers.lua b/Libs/DF/containers.lua index 60a653cb..3864d216 100644 --- a/Libs/DF/containers.lua +++ b/Libs/DF/containers.lua @@ -8,84 +8,81 @@ local _ local DF = detailsFramework local CreateFrame = CreateFrame +local wipe = wipe +local unpack = unpack ----@class framecontainer : frame +---@class dfframecontainer : frame, dfframecontainermixin, dfoptionsmixin ---@field bIsSizing boolean ---@field options table ----@field leftResizer button ----@field rightResizer button ----@field OnSizeChanged fun(frameContainer: framecontainer) +---@field currentWidth number +---@field currentHeight number +---@field bottomLeftResizer framecontainerresizer +---@field bottomRightResizer framecontainerresizer +---@field topLeftResizer framecontainerresizer +---@field topRightResizer framecontainerresizer +---@field topResizer framecontainerresizer +---@field bottomResizer framecontainerresizer +---@field leftResizer framecontainerresizer +---@field rightResizer framecontainerresizer +---@field cornerResizers framecontainerresizer[] +---@field sideResizers framecontainerresizer[] +---@field components table +---@field moverFrame frame +---@field movableChildren frame[] +---@field OnSizeChanged fun(frameContainer: dfframecontainer) ---@field OnResizerMouseDown fun(resizerButton: button, mouseButton: string) ---@field OnResizerMouseUp fun(resizerButton: button, mouseButton: string) ----@field HideResizer fun(frameContainer: framecontainer) ----@field ShowResizer fun(frameContainer: framecontainer) ----@field OnInitialize fun(frameContainer: framecontainer) ----@field SetLocked fun(frameContainer: framecontainer, isLocked: boolean) ----@field CheckLockedState fun(frameContainer: framecontainer) +---@field HideResizer fun(frameContainer: dfframecontainer) +---@field ShowResizer fun(frameContainer: dfframecontainer) +---@field OnInitialize fun(frameContainer: dfframecontainer) +---@field SetResizeLocked fun(frameContainer: dfframecontainer, isLocked: boolean) +---@field SetMovableLocked fun(frameContainer: dfframecontainer, isLocked: boolean) +---@field CheckResizeLockedState fun(frameContainer: dfframecontainer) +---@field CheckMovableLockedState fun(frameContainer: dfframecontainer) +---@field CreateMover fun(frameContainer: dfframecontainer) +---@field CreateResizers fun(frameContainer: dfframecontainer) +---@field RegisterChildForDrag fun(frameContainer: dfframecontainer, child: frame) +---@field UnregisterChildForDrag fun(frameContainer: dfframecontainer, child: frame) +---@field RefreshChildrenState fun(frameContainer: dfframecontainer) +---@field OnChildDragStart fun(frameContainer: dfframecontainer, child: frame) +---@field OnChildDragStop fun(frameContainer: dfframecontainer, child: frame) -detailsFramework.frameContainerMixin = { + + +---@class framecontainerresizer : button +---@field sizingFrom string + +---@class dfframecontainermixin +detailsFramework.FrameContainerMixin = { --methods - ---run when the container has its size changed - ---@param frameContainer framecontainer - OnSizeChanged = function(frameContainer) - ---@type frame[] - local children = {frameContainer:GetChildren()} - ---@type number - local childrenAmount = #children - - --get the width of each children and sum the values, do the same thing for height - ---@type number - local childrenWidth = 0 - ---@type number - local childrenHeight = 0 - - for i = 1, childrenAmount do - childrenWidth = childrenWidth + children[i]:GetWidth() - childrenHeight = childrenHeight + children[i]:GetHeight() - end - - print("running...") - - --if the children width is bigger than the container width, then need to resize the width of the children to porportionally fit the container - --this resize is done by getting the width of each child and reduce the width of the child by the percentage of the difference between the container width and the children width - if childrenWidth > frameContainer:GetWidth() then - ---@type number - local widthDifference = childrenWidth - frameContainer:GetWidth() - - for i = 1, childrenAmount do - children[i]:SetWidth(children[i]:GetWidth() - (children[i]:GetWidth() * (widthDifference / childrenWidth))) - end - end - end, ---run when the user click on the resizer - ---@param resizerButton button + ---@param resizerButton framecontainerresizer ---@param mouseButton string OnResizerMouseDown = function(resizerButton, mouseButton) if (mouseButton ~= "LeftButton") then return end -print(1) - ---@type framecontainer - local frameContainer = resizerButton:GetParent() --Cannot assign `frame` to `framecontainer`. .. but framecontainer is inherited from frame + + ---@type dfframecontainer + local frameContainer = resizerButton:GetParent() --Cannot assign `frame` to `dfframecontainer`. .. but dfframecontainer is inherited from frame if (frameContainer.bIsSizing) then return end frameContainer.bIsSizing = true - frameContainer:StartSizing("bottomright") + frameContainer:StartSizing(resizerButton.sizingFrom) end, ---run when the user click on the resizer - ---@param resizerButton button + ---@param resizerButton framecontainerresizer ---@param mouseButton string OnResizerMouseUp = function(resizerButton, mouseButton) - ---@type framecontainer - local frameContainer = resizerButton:GetParent() --Cannot assign `frame` to `framecontainer`. .. but framecontainer is inherited from frame - print(2) + ---@type dfframecontainer + local frameContainer = resizerButton:GetParent() --Cannot assign `frame` to `dfframecontainer`. .. but dfframecontainer is inherited from frame + if (not frameContainer.bIsSizing) then - print("fuck") return end @@ -94,15 +91,41 @@ print(1) end, ---hide resizer - ---@param frameContainer framecontainer + ---@param frameContainer dfframecontainer HideResizer = function(frameContainer) - frameContainer.leftResizer:Hide() - frameContainer.rightResizer:Hide() + for i = 1, #frameContainer.cornerResizers do + frameContainer.cornerResizers[i]:Hide() + end + + for i = 1, #frameContainer.sideResizers do + frameContainer.sideResizers[i]:Hide() + end end, ---show resizer - ---@param frameContainer framecontainer + ---@param frameContainer dfframecontainer ShowResizer = function(frameContainer) + --corner resizers + if (frameContainer.options.use_bottomleft_resizer) then + frameContainer.bottomLeftResizer:Show() + end + if (frameContainer.options.use_bottomright_resizer) then + frameContainer.bottomRightResizer:Show() + end + if (frameContainer.options.use_topleft_resizer) then + frameContainer.topRightResizer:Show() + end + if (frameContainer.options.use_topright_resizer) then + frameContainer.topRightResizer:Show() + end + + --side resizers + if (frameContainer.options.use_top_resizer) then + frameContainer.topResizer:Show() + end + if (frameContainer.options.use_bottom_resizer) then + frameContainer.bottomResizer:Show() + end if (frameContainer.options.use_left_resizer) then frameContainer.leftResizer:Show() end @@ -112,110 +135,391 @@ print(1) end, ---check the lock state and show or hide the resizer, set the frame as movable or not, resizeable or not - ---@param frameContainer framecontainer - CheckLockedState = function(frameContainer) - if (frameContainer.options.is_locked) then - frameContainer:HideResizer() - frameContainer:EnableMouse(false) - frameContainer:SetResizable(false) - else + ---@param frameContainer dfframecontainer + CheckResizeLockedState = function(frameContainer) + if (frameContainer.options.can_resize) then frameContainer:ShowResizer() - frameContainer:EnableMouse(true) frameContainer:SetResizable(true) + else + frameContainer:HideResizer() + frameContainer:SetResizable(false) + end + end, + + ---check if the framecontainer can be moved and show or hide the mover + ---@param frameContainer dfframecontainer + CheckMovableLockedState = function(frameContainer) + if (frameContainer.options.can_move) then + frameContainer:SetMovable(true) + frameContainer:EnableMouse(true) + frameContainer.moverFrame:Show() + else + frameContainer:SetMovable(false) + frameContainer:EnableMouse(false) + frameContainer.moverFrame:Hide() end end, ---set the lock state - ---@param frameContainer framecontainer + ---@param frameContainer dfframecontainer ---@param isLocked boolean - SetLocked = function(frameContainer, isLocked) - frameContainer.options.is_locked = isLocked - frameContainer:CheckLockedState() + SetResizeLocked = function(frameContainer, isLocked) + frameContainer.options.can_resize = not isLocked + frameContainer:CheckResizeLockedState() + end, + + ---set the state of the mover frame + ---@param frameContainer dfframecontainer + ---@param isLocked boolean + SetMovableLocked = function(frameContainer, isLocked) + frameContainer.options.can_move = not isLocked + frameContainer:CheckMovableLockedState() + end, + + ---create a mover to move the frame + ---@param frameContainer dfframecontainer + CreateMover = function(frameContainer) + local mover = CreateFrame("button", nil, frameContainer) + frameContainer.moverFrame = mover + mover:SetAllPoints(frameContainer) + mover:SetMovable(true) + mover:SetScript("OnMouseDown", function(self, mouseButton) + if (mouseButton ~= "LeftButton" or not frameContainer.options.can_move) then + return + end + frameContainer:StartMoving() + end) + mover:SetScript("OnMouseUp", function(self, mouseButton) + if (mouseButton ~= "LeftButton" or not frameContainer.options.can_move) then + return + end + frameContainer:StopMovingOrSizing() + end) + end, + + ---create four corner resizer and four side resizer + ---@param frameContainer dfframecontainer + CreateResizers = function(frameContainer) + local parent = frameContainer:GetParent() + --create resizers for the container corners + local bottomLeftResizer, bottomRightResizer = detailsFramework:CreateResizeGrips(frameContainer, nil, parent:GetName() .. "BottomLeftResizer", parent:GetName() .. "BottomRightResizer") + frameContainer.bottomLeftResizer = bottomLeftResizer + frameContainer.bottomRightResizer = bottomRightResizer + + local topLeftResizer, topRightResizer = detailsFramework:CreateResizeGrips(frameContainer, nil, parent:GetName() .. "TopLeftResizer", parent:GetName() .. "TopRightResizer") + frameContainer.topLeftResizer = topLeftResizer + frameContainer.topRightResizer = topRightResizer + + local topResizer, bottomResizer = detailsFramework:CreateResizeGrips(frameContainer, nil, parent:GetName() .. "TopResizer", parent:GetName() .. "BottomResizer") + frameContainer.topResizer = topResizer + frameContainer.bottomResizer = bottomResizer + + local leftResizer, rightResizer = detailsFramework:CreateResizeGrips(frameContainer, nil, parent:GetName() .. "LeftResizer", parent:GetName() .. "TopResizer") + frameContainer.leftResizer = leftResizer + frameContainer.rightResizer = rightResizer + + frameContainer.cornerResizers = { + bottomLeftResizer, + bottomRightResizer, + topLeftResizer, + topRightResizer, + } + + frameContainer.sideResizers = { + topResizer, + bottomResizer, + leftResizer, + rightResizer, + } + + --add all resizers to the frameContainer.components table + for i = 1, #frameContainer.cornerResizers do + frameContainer.components[frameContainer.cornerResizers[i]] = true + frameContainer.cornerResizers[i]:SetFrameStrata("TOOLTIP") + end + for i = 1, #frameContainer.sideResizers do + frameContainer.components[frameContainer.sideResizers[i]] = true + frameContainer.sideResizers[i]:SetFrameStrata("TOOLTIP") + end end, ---run when the container is created - ---@param frameContainer framecontainer - OnInitialize = function(frameContainer) - frameContainer.leftResizer:SetScript("OnMouseDown", frameContainer.OnResizerMouseDown) - frameContainer.leftResizer:SetScript("OnMouseUp", frameContainer.OnResizerMouseUp) - frameContainer.rightResizer:SetScript("OnMouseDown", frameContainer.OnResizerMouseDown) - frameContainer.rightResizer:SetScript("OnMouseUp", frameContainer.OnResizerMouseUp) + ---@param frameContainer dfframecontainer + OnInitialize = function(frameContainer) --õninit ~init ~oninit + --set the default members + frameContainer.bIsSizing = false + frameContainer:SetSize(frameContainer.options.width, frameContainer.options.height) - if (frameContainer.options.is_locked) then - frameContainer:HideResizer() - else - frameContainer:ShowResizer() + --iterate among the corner resizers and set the mouse down and up scripts + for i = 1, #frameContainer.cornerResizers do + frameContainer.cornerResizers[i]:SetScript("OnMouseDown", frameContainer.OnResizerMouseDown) + frameContainer.cornerResizers[i]:SetScript("OnMouseUp", frameContainer.OnResizerMouseUp) end - frameContainer:CheckLockedState() + local sideResizeThickness = 3 + --iterate among the side resizers and set the mouse down and up scripts; set the texture color; clear all points; set the thickness + for i = 1, #frameContainer.sideResizers do + frameContainer.sideResizers[i]:SetScript("OnMouseDown", frameContainer.OnResizerMouseDown) + frameContainer.sideResizers[i]:SetScript("OnMouseUp", frameContainer.OnResizerMouseUp) + + frameContainer.sideResizers[i]:GetNormalTexture():SetColorTexture(1, 1, 1, 0.6) + frameContainer.sideResizers[i]:GetHighlightTexture():SetColorTexture(detailsFramework:ParseColors("aqua")) + frameContainer.sideResizers[i]:GetPushedTexture():SetColorTexture(1, 1, 1, 1) + + frameContainer.sideResizers[i]:ClearAllPoints() + + --can use SetSize here because the width or height are set by the point, e.g. 'topleft' to 'topright' overwrite the width set here + frameContainer.sideResizers[i]:SetSize(sideResizeThickness, sideResizeThickness) + end + + --flip the corner resizers texturess + frameContainer.topLeftResizer:GetNormalTexture():SetTexCoord(1, 0, 1, 0) + frameContainer.topLeftResizer:GetHighlightTexture():SetTexCoord(1, 0, 1, 0) + frameContainer.topLeftResizer:GetPushedTexture():SetTexCoord(1, 0, 1, 0) + frameContainer.topRightResizer:GetNormalTexture():SetTexCoord(0, 1, 1, 0) + frameContainer.topRightResizer:GetHighlightTexture():SetTexCoord(0, 1, 1, 0) + frameContainer.topRightResizer:GetPushedTexture():SetTexCoord(0, 1, 1, 0) + frameContainer.topLeftResizer:ClearAllPoints() + frameContainer.topLeftResizer:SetPoint("topleft", frameContainer, "topleft", 0, 0) + frameContainer.topRightResizer:ClearAllPoints() + frameContainer.topRightResizer:SetPoint("topright", frameContainer, "topright", 0, 0) + + --resize from for the corner resizers + frameContainer.bottomLeftResizer.sizingFrom = "bottomleft" + frameContainer.bottomRightResizer.sizingFrom = "bottomright" + frameContainer.topLeftResizer.sizingFrom = "topleft" + frameContainer.topRightResizer.sizingFrom = "topright" + + --resize from for the side resizers + frameContainer.topResizer.sizingFrom = "top" + frameContainer.bottomResizer.sizingFrom = "bottom" + frameContainer.leftResizer.sizingFrom = "left" + frameContainer.rightResizer.sizingFrom = "right" + + --set the side resizer points + frameContainer.topResizer:SetPoint("topleft", frameContainer, "topleft", 0, 0) + frameContainer.topResizer:SetPoint("topright", frameContainer, "topright", 0, 0) + frameContainer.bottomResizer:SetPoint("bottomleft", frameContainer, "bottomleft", 0, 0) + frameContainer.bottomResizer:SetPoint("bottomright", frameContainer, "bottomright", 0, 0) + frameContainer.leftResizer:SetPoint("topleft", frameContainer, "topleft", 0, 0) + frameContainer.leftResizer:SetPoint("bottomleft", frameContainer, "bottomleft", 0, 0) + frameContainer.rightResizer:SetPoint("topright", frameContainer, "topright", 0, 0) + frameContainer.rightResizer:SetPoint("bottomright", frameContainer, "bottomright", 0, 0) + + if (frameContainer.options.can_resize) then + frameContainer:ShowResizer() + else + frameContainer:HideResizer() + end + + frameContainer:CheckResizeLockedState() + frameContainer:CheckMovableLockedState() frameContainer:SetResizeBounds(50, 50, 1000, 1000) end, + ---run when the container has its size changed + ---@param frameContainer dfframecontainer + OnSizeChanged = function(frameContainer) + ---@type frame[] + local children = {frameContainer:GetChildren()} + ---@type number + local childrenAmount = #children + + --get the container size before its size was changed and calculate the percent of the difference between the old size and the new size + --adding +1 to the width and height difference to prevent the child from shrinking to 0, so it is scaled by 1 + ---@type number + local widthDifference = 1 + (frameContainer:GetWidth() - frameContainer.currentWidth) / frameContainer.currentWidth + ---@type number + local heightDifference = 1 + (frameContainer:GetHeight() - frameContainer.currentHeight) / frameContainer.currentHeight + + for i = 1, childrenAmount do + ---@type frame + local child = children[i] + --if the child is a component, skip it + if (not frameContainer.components[child]) then + child:SetWidth(child:GetWidth() * widthDifference) + child:SetHeight(child:GetHeight() * heightDifference) + end + end + + --update the current size of the container + frameContainer.currentWidth = frameContainer:GetWidth() + frameContainer.currentHeight = frameContainer:GetHeight() + end, + + OnChildDragStop = function(child) + child:StopMovingOrSizing() + child:SetScript("OnUpdate", nil) + end, + + OnChildDragStart = function(child) + ---@type dfframecontainer + local frameContainer = child:GetParent() + + ---get the coordinates for the frame container, which is called 'boundingBox' for convenience + ---@type objectcoordinates + local boundingBox = detailsFramework:GetObjectCoordinates(frameContainer) + + child:StartMoving() + + --save the current point of the child, so it can be restored if the child is dragged outside the container + local childPoints = {} + for pointIndex = 1, child:GetNumPoints() do + childPoints[pointIndex] = {child:GetPoint(pointIndex)} + end + + child:SetScript("OnUpdate", function(self) + ---@type objectcoordinates + local childPos = detailsFramework:GetObjectCoordinates(self) + --check if the borders of the rectangle 'rec' collided with the borders of the rectangle 'bbox' + if ((childPos.left < boundingBox.left or childPos.right > boundingBox.right) or (childPos.top > boundingBox.top or childPos.bottom < boundingBox.bottom)) then + child:ClearAllPoints() + for pointIndex = 1, #childPoints do + child:SetPoint(unpack(childPoints[pointIndex])) + end + else + wipe(childPoints) + for pointIndex = 1, child:GetNumPoints() do + childPoints[pointIndex] = {child:GetPoint(pointIndex)} + end + end + end) + end, + + ---check if the children can be moved and set the properties on thisFrame + ---@param frameContainer dfframecontainer + RefreshChildrenState = function(frameContainer) + frameContainer:EnableMouse(true) + if (frameContainer.options.can_move_children) then + for child, _ in pairs(frameContainer.movableChildren) do + child:EnableMouse(true) + child:SetMovable(true) + child:RegisterForDrag("LeftButton") + child:SetScript("OnDragStart", detailsFramework.FrameContainerMixin.OnChildDragStart) + child:SetScript("OnDragStop", detailsFramework.FrameContainerMixin.OnChildDragStop) + end + else + for child, _ in pairs(frameContainer.movableChildren) do + child:EnableMouse(false) + child:SetMovable(false) + child:RegisterForDrag("") + child:SetScript("OnDragStart", nil) + child:SetScript("OnDragStop", nil) + end + end + end, + + RegisterChildForDrag = function(frameContainer, child) + frameContainer.movableChildren[child] = true + frameContainer:RefreshChildrenState() + end, + + UnregisterChildForDrag = function(frameContainer, child) + frameContainer.movableChildren[child] = nil + frameContainer:RefreshChildrenState() + end, } +---these are the default settings for the frame container; these keys can be accessed by dfframecontainer.options[key] +---@type table local frameContainerOptions = { --default settings width = 300, height = 150, - is_locked = false, + can_resize = false, --can or not be resized + can_move = false, --can or not be moved + can_move_children = true, + use_topleft_resizer = false, + use_topright_resizer = false, + use_bottomleft_resizer = false, + use_bottomright_resizer = true, + use_top_resizer = false, + use_bottom_resizer = false, use_left_resizer = false, - use_right_resizer = true, + use_right_resizer = false, } ---create a frame container, which is a frame that envelops another frame, and can be moved, resized, etc. ---@param parent frame ---@param options table|nil ---@param frameName string|nil ----@return framecontainer +---@return dfframecontainer function DF:CreateFrameContainer(parent, options, frameName) - ---@type framecontainer - local container = CreateFrame("frame", frameName or ("$parentFrameContainer" .. math.random(10000, 99999)), parent, "BackdropTemplate") + ---@type dfframecontainer + local frameContainer = CreateFrame("frame", frameName or ("$parentFrameContainer" .. math.random(10000, 99999)), parent, "BackdropTemplate") + frameContainer.components = {} + frameContainer.movableChildren = {} - detailsFramework:Mixin(container, detailsFramework.frameContainerMixin) - detailsFramework:Mixin(container, detailsFramework.OptionsFunctions) + detailsFramework:Mixin(frameContainer, detailsFramework.FrameContainerMixin) + detailsFramework:Mixin(frameContainer, detailsFramework.OptionsFunctions) - detailsFramework:CreateResizeGrips(container) + frameContainer:CreateResizers() + frameContainer:CreateMover() + frameContainer:BuildOptionsTable(frameContainerOptions, options) - container:BuildOptionsTable(frameContainerOptions, options) + frameContainer:OnInitialize() - container:SetScript("OnSizeChanged", container.OnSizeChanged) + frameContainer.currentWidth = frameContainer:GetWidth() + frameContainer.currentHeight = frameContainer:GetHeight() + frameContainer:SetScript("OnSizeChanged", frameContainer.OnSizeChanged) - container.bIsSizing = false - - container:OnInitialize() - - return container + return frameContainer end -function DF:CreateFrameContainerTest(parent, options, frameName) + + +function DF:CreateFrameContainerTest(parent, options, frameName) local container = DF:CreateFrameContainer(parent, options, frameName) container:SetSize(400, 400) - container:SetPoint("center", UIParent, "center", 0, 0) + container:SetPoint("center", _G.UIParent, "center", 0, 0) detailsFramework:ApplyStandardBackdrop(container) - for i = 1, 3 do - for o = 1, 3 do - local frame = CreateFrame("frame", "$parentFrame" .. math.random(10000, 99999), container, "BackdropTemplate") - frame:SetBackdrop({bgFile = "Interface\\AddOns\\Details\\images\\background", tile = true, tileSize = 16, edgeFile = "Interface\\AddOns\\Details\\images\\border_2", edgeSize = 16, insets = {left = 4, right = 4, top = 4, bottom = 4}}) + local verticalLastBox = nil + for i = 1, 4 do + local lastBox = nil + for o = 1, 4 do + local frame = CreateFrame("frame", "$parentFrame" .. i .. o, container, "BackdropTemplate") + container:RegisterChildForDrag(frame) + + frame:SetBackdrop({edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1, bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true}) frame:SetBackdropColor(0, 0, 0, 0.5) frame:SetBackdropBorderColor(1, 1, 1, 0.5) - frame:SetSize(100, 100) - frame:SetPoint("TOPLEFT", container, "TOPLEFT", 10 + (i - 1) * 110, -10 - (o - 1) * 110) + frame:SetSize(98, 98) + if (lastBox) then + frame:SetPoint("TOPLEFT", lastBox, "topright", 1, 0) + else + if (verticalLastBox) then + frame:SetPoint("TOPLEFT", verticalLastBox, "bottomleft", 0, -1) + verticalLastBox = frame + else + local x = 1 + (o - 1) * 99 + local y = -10 - (i - 1) * 99 + frame:SetPoint("TOPLEFT", container, "TOPLEFT", x, y) + verticalLastBox = frame + end + end + lastBox = frame end end + + C_Timer.After(2, function() + --container:SetResizeLocked(true) + end) end -C_Timer.After(2, function() - --DetailsFramework:CreateFrameContainerTest(UIParent) -end) +--C_Timer.After(2, function() +-- DetailsFramework:CreateFrameContainerTest(UIParent) +--end) --[=[ /run DetailsFramework:CreateFrameContainerTest(UIParent) C_Timer.After(2, function() DetailsFramework:CreateFrameContainerTest(UIParent) - end) + end) + + --]=] \ No newline at end of file diff --git a/Libs/DF/math.lua b/Libs/DF/math.lua index 793b9dda..85706e59 100644 --- a/Libs/DF/math.lua +++ b/Libs/DF/math.lua @@ -121,6 +121,56 @@ function DF:Round(num, numDecimalPlaces) return math.floor(num * mult + 0.5) / mult end +local BoundingBox = {} +BoundingBox.CoordinatesData = { + ["topleft"] = {["x"] = 'number', ["y"] = 'number'}, + ["topright"] = {["x"] = 'number', ["y"] = 'number'}, + ["bottomleft"] = {["x"] = 'number', ["y"] = 'number'}, + ["bottomright"] = {["x"] = 'number', ["y"] = 'number'}, + ["center"] = {["x"] = 'number', ["y"] = 'number'}, + ["width"] = 'number', + ["height"] = 'number', +} + +---@class objectcoordinates +---@field topleft {["x"]: number, ["y"]: number} +---@field topright {["x"]: number, ["y"]: number} +---@field bottomleft {["x"]: number, ["y"]: number} +---@field bottomright {["x"]: number, ["y"]: number} +---@field center {["x"]: number, ["y"]: number} +---@field width number +---@field height number +---@field left number +---@field right number +---@field top number +---@field bottom number + +---return the coordinates of the four corners of an object +---@param object uiobject +---@return objectcoordinates +function DF:GetObjectCoordinates(object) + local centerX, centerY = object:GetCenter() + local width = object:GetWidth() + local height = object:GetHeight() + + local halfWidth = width / 2 + local halfHeight = height / 2 + + return { + ["width"] = width, + ["height"] = height, + ["left"] = centerX - halfWidth, + ["right"] = centerX + halfWidth, + ["top"] = centerY + halfHeight, + ["bottom"] = centerY - halfHeight, + ["center"] = {x = centerX, y = centerY}, + ["topleft"] = {x = centerX - halfWidth, y = centerY + halfHeight}, + ["topright"] = {x = centerX + halfWidth, y = centerY + halfHeight}, + ["bottomleft"] = {x = centerX - halfWidth, y = centerY - halfHeight}, + ["bottomright"] = {x = centerX + halfWidth, y = centerY - halfHeight}, + } +end + function DF:ScaleBack() end diff --git a/Libs/DF/mixins.lua b/Libs/DF/mixins.lua index 123d721d..c8389196 100644 --- a/Libs/DF/mixins.lua +++ b/Libs/DF/mixins.lua @@ -268,6 +268,7 @@ detailsFramework.SetPointMixin = { } ---mixin for options +---@class dfoptionsmixin detailsFramework.OptionsFunctions = { SetOption = function(self, optionName, optionValue) if (self.options) then diff --git a/Libs/DF/panel.lua b/Libs/DF/panel.lua index 84935ec7..ce6e3bbe 100644 --- a/Libs/DF/panel.lua +++ b/Libs/DF/panel.lua @@ -3919,43 +3919,41 @@ local rezieGripOptions = { ---create the two resize grips for a frame, one in the bottom left and another in the bottom right ---@param parent frame +---@param options table|nil +---@param leftResizerName string|nil +---@param rightResizerName string|nil ---@return frame, frame -function detailsFramework:CreateResizeGrips(parent, options, frameName) - if (parent) then - local parentName = parent:GetName() +function detailsFramework:CreateResizeGrips(parent, options, leftResizerName, rightResizerName) + local parentName = parent:GetName() - local leftResizer = CreateFrame("button", frameName or (parentName and "$parentLeftResizer"), parent, "BackdropTemplate") - local rightResizer = CreateFrame("button", frameName or (parentName and "$parentRightResizer"), parent, "BackdropTemplate") + local leftResizer = _G.CreateFrame("button", leftResizerName or (parentName and "$parentLeftResizer"), parent, "BackdropTemplate") + local rightResizer = _G.CreateFrame("button", rightResizerName or (parentName and "$parentRightResizer"), parent, "BackdropTemplate") - parent.leftResizer = leftResizer - parent.rightResizer = rightResizer + detailsFramework:Mixin(leftResizer, detailsFramework.OptionsFunctions) + detailsFramework:Mixin(rightResizer, detailsFramework.OptionsFunctions) + leftResizer:BuildOptionsTable(rezieGripOptions, options) + rightResizer:BuildOptionsTable(rezieGripOptions, options) - detailsFramework:Mixin(leftResizer, detailsFramework.OptionsFunctions) - detailsFramework:Mixin(rightResizer, detailsFramework.OptionsFunctions) - leftResizer:BuildOptionsTable(rezieGripOptions, options) - rightResizer:BuildOptionsTable(rezieGripOptions, options) + leftResizer:SetPoint("bottomleft", parent, "bottomleft", 0, 0) + rightResizer:SetPoint("bottomright", parent, "bottomright", 0, 0) + leftResizer:SetSize(leftResizer.options.width, leftResizer.options.height) + rightResizer:SetSize(leftResizer.options.width, leftResizer.options.height) - leftResizer:SetPoint("bottomleft", parent, "bottomleft", 0, 0) - rightResizer:SetPoint("bottomright", parent, "bottomright", 0, 0) - leftResizer:SetSize(leftResizer.options.width, leftResizer.options.height) - rightResizer:SetSize(leftResizer.options.width, leftResizer.options.height) + rightResizer:SetNormalTexture(rightResizer.options.normal_texture) + rightResizer:SetHighlightTexture(rightResizer.options.highlight_texture) + rightResizer:SetPushedTexture(rightResizer.options.pushed_texture) - rightResizer:SetNormalTexture(rightResizer.options.normal_texture) - rightResizer:SetHighlightTexture(rightResizer.options.highlight_texture) - rightResizer:SetPushedTexture(rightResizer.options.pushed_texture) + leftResizer:SetNormalTexture(leftResizer.options.normal_texture) + leftResizer:SetHighlightTexture(leftResizer.options.highlight_texture) + leftResizer:SetPushedTexture(leftResizer.options.pushed_texture) - leftResizer:SetNormalTexture(leftResizer.options.normal_texture) - leftResizer:SetHighlightTexture(leftResizer.options.highlight_texture) - leftResizer:SetPushedTexture(leftResizer.options.pushed_texture) - - if (leftResizer.options.should_mirror_left_texture) then - leftResizer:GetNormalTexture():SetTexCoord(1, 0, 0, 1) - leftResizer:GetHighlightTexture():SetTexCoord(1, 0, 0, 1) - leftResizer:GetPushedTexture():SetTexCoord(1, 0, 0, 1) - end - - return leftResizer, rightResizer + if (leftResizer.options.should_mirror_left_texture) then + leftResizer:GetNormalTexture():SetTexCoord(1, 0, 0, 1) + leftResizer:GetHighlightTexture():SetTexCoord(1, 0, 0, 1) + leftResizer:GetPushedTexture():SetTexCoord(1, 0, 0, 1) end + + return leftResizer, rightResizer end diff --git a/frames/window_playerbreakdown_spells.lua b/frames/window_playerbreakdown_spells.lua index 1d297b33..7dba9966 100644 --- a/frames/window_playerbreakdown_spells.lua +++ b/frames/window_playerbreakdown_spells.lua @@ -1258,13 +1258,28 @@ end ---@param tabFrame tabframe ---@return breakdownspellscrollframe function spellsTab.CreateSpellScrollContainer(tabFrame) + --create a container for the scrollframe + local options = { + width = CONST_SPELLSCROLL_WIDTH, + height = CONST_SPELLSCROLL_HEIGHT, + can_resize = false, + can_move = false, + can_move_children = false, + use_bottom_resizer = true, + use_right_resizer = true, + } + ---@type dfframecontainer + local container = DF:CreateFrameContainer(tabFrame, options, tabFrame:GetName() .. "SpellScrollContainer") + container:SetPoint("topleft", tabFrame, "topleft", 5, -5) + --replace this with a framework scrollframe - local scrollFrame = DF:CreateScrollBox(tabFrame, "$parentSpellScroll", refreshFunc, {}, CONST_SPELLSCROLL_WIDTH, CONST_SPELLSCROLL_HEIGHT, CONST_SPELLSCROLL_AMTLINES, CONST_SPELLSCROLL_LINEHEIGHT) + local scrollFrame = DF:CreateScrollBox(container, "$parentSpellScroll", refreshFunc, {}, CONST_SPELLSCROLL_WIDTH, CONST_SPELLSCROLL_HEIGHT, CONST_SPELLSCROLL_AMTLINES, CONST_SPELLSCROLL_LINEHEIGHT) DF:ReskinSlider(scrollFrame) DF:ApplyStandardBackdrop(scrollFrame) - scrollFrame:SetPoint("topleft", tabFrame, "topleft", 5, -5) --need to set the points - scrollFrame:EnableMouse(true) - scrollFrame:SetMovable(true) + container:RegisterChildForDrag(scrollFrame) + scrollFrame:SetPoint("topleft", container, "topleft", 0, 0) --need to set the points + --scrollFrame:EnableMouse(true) + --scrollFrame:SetMovable(true) scrollFrame.DontHideChildrenOnPreRefresh = true tabFrame.SpellScrollFrame = scrollFrame spellsTab.SpellScrollFrame = scrollFrame @@ -1307,6 +1322,7 @@ function spellsTab.CreateSpellScrollContainer(tabFrame) --here need an api from the header frame to get the key to sort print("key:", key) + --problem: ----- --pre process the data which may be used into the scroll