You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

243 lines
7.1 KiB

5 years ago
--[[
GridView.lua
@Author : DengSir (tdaddon@163.com)
@Link : https://dengsir.github.io
]]
local MAJOR, MINOR = 'GridView', 5
local GUI = LibStub('tdGUI-1.0')
local GridView = GUI:NewClass(MAJOR, MINOR, 'Frame', 'Refresh', 'View', 'Select', 'Owner', 'Backdrop')
if not GridView then return end
function GridView:Constructor()
self._buttons = {}
self:SetSelectMode('NONE')
self:SetScript('OnShow', self.Refresh)
self:SetScript('OnSizeChanged', self.OnSizeChanged)
local scrollBar = CreateFrame('Slider', nil, self, 'UIPanelScrollBarTemplate') do
self.scrollBar = scrollBar
self.scrollUp = scrollBar.ScrollUpButton
self.scrollDown = scrollBar.ScrollDownButton
scrollBar.thumbTexture = scrollBar.ThumbTexture
scrollBar:SetValueStep(1)
scrollBar:SetStepsPerPage(1)
scrollBar:SetPoint('TOPRIGHT', 0, -18)
scrollBar:SetPoint('BOTTOMRIGHT', 0, 18)
scrollBar:SetScript('OnValueChanged', function(scrollBar, value)
HybridScrollFrame_UpdateButtonStates(self, value)
self:SetOffset(value)
end)
scrollBar:SetScript('OnMinMaxChanged', function(scrollBar, minValue, maxValue)
scrollBar:SetShown(minValue ~= maxValue)
end)
scrollBar:SetScript('OnShow', function(scrollBar)
self:Refresh()
end)
scrollBar:SetScript('OnHide', function(scrollBar)
self:Refresh()
end)
end
self:EnableMouseWheel(true)
self:SetScript('OnMouseWheel', self.OnMouseWheel)
end
function GridView:SetOffset(value)
local offset = math.floor(value + 0.5)
if self._offset ~= offset then
self._offset = offset
self:Refresh()
end
end
function GridView:GetOffset()
return self._offset or 1
end
function GridView:OnMouseWheel(delta)
self.scrollBar:SetValue(self.scrollBar:GetValue() - self.scrollBar:GetValueStep() * delta)
end
function GridView:OnSizeChanged()
self._rowCount = nil
self:UpdateLayout()
self:Refresh()
end
function GridView:Update()
self:UpdateScrollBar()
self:UpdateItems()
self:UpdateLayout()
end
function GridView:GetMaxCount()
return self:GetRowCount() * self:GetColumnCount()
end
function GridView:UpdateScrollBar()
local maxCount = self:GetMaxCount()
local itemCount = self:GetItemCount()
local maxValue = itemCount <= maxCount and 1 or itemCount - maxCount + 1
self.scrollBar:SetMinMaxValues(1, maxValue)
self.scrollBar:SetValue(self:GetOffset())
end
function GridView:UpdateLayout()
for i in ipairs(self._buttons) do
self:UpdateItemPosition(i)
end
end
function GridView:UpdateItemPosition(i)
local button = self:GetButton(i)
local itemSpacingV, itemSpacingH = self:GetItemSpacing()
local itemHeight = self:GetItemHeight()
local itemWidth = self:GetItemWidth()
local lineCount = self:GetColumnCount()
local left, right, top, bottom = self:GetPadding()
right = right + self:GetScrollBarFixedWidth()
button:ClearAllPoints()
if lineCount == 1 then
button:SetHeight(itemHeight)
button:SetPoint('TOPLEFT', left, -top-(i-1)*(itemHeight+itemSpacingV))
button:SetPoint('TOPRIGHT', -right, -top-(i-1)*(itemHeight+itemSpacingV))
else
local row = floor((i-1)/lineCount)
local col = (i-1)%lineCount
button:SetSize(itemWidth, itemHeight)
button:SetPoint('TOPLEFT', left+col*(itemWidth+itemSpacingH), -top-row*(itemHeight+itemSpacingV))
end
end
function GridView:UpdateItems()
if not self:GetRight() then
return
end
local offset = self:GetOffset()
local maxCount = min(self:GetColumnCount() * self:GetRowCount(), self:GetItemCount())
local autoWidth = self:GetItemWidth() or 1
local maxRight = 0
local column = self:GetColumnCount()
offset = ceil((offset - 1) / column) * column + 1
for i = 1, maxCount do
local button = self:GetButton(i)
local index = offset + i - 1
if self:GetItem(index) then
button:SetID(index)
button:SetChecked(self:IsSelected(index))
button:Show()
button:FireFormat()
autoWidth = max(autoWidth, button:GetAutoWidth() or 0)
maxRight = max(maxRight, button:GetRight())
else
button:Hide()
end
end
for i = maxCount + 1, #self._buttons do
self:GetButton(i):Hide()
end
if maxCount > 0 and self:IsAutoSize() then
local left, right, top, bottom = self:GetPadding()
local height = self:GetTop() - self:GetButton(maxCount):GetBottom() + bottom
local width = self:GetScrollBarFixedWidth()
if self:GetColumnCount() == 1 then
width = width + autoWidth + left + right
else
width = width + maxRight - self:GetLeft() + right
end
self:SetSize(width, height)
end
end
function GridView:SetColumnCount(columnCount)
self._columnCount = columnCount
self:SetScrollStep(columnCount)
end
function GridView:GetColumnCount()
return self._columnCount or 1
end
function GridView:SetRowCount(rowCount)
self._rowCount = rowCount
self:SetScript('OnSizeChanged', nil)
end
function GridView:GetRowCount()
if not self._rowCount then
if self._autoSize then
return self:GetItemCount()
else
local itemHeight = self:GetItemHeight()
local itemSpacing = self:GetItemSpacing()
local top, bottom = select(2, self:GetPadding())
local height = self:GetHeight() - top - bottom + itemSpacing
self._rowCount = floor(height / (itemHeight + itemSpacing))
end
end
return self._rowCount
end
function GridView:SetAutoSize(_autoSize)
self._autoSize = _autoSize
self:SetScript('OnSizeChanged', not autosize and self.OnSizeChanged or nil)
self:SetSize(1, 1)
end
function GridView:IsAutoSize()
return self._autoSize
end
function GridView:GetItemWidth()
if not self._autoSize then
local left, right = self:GetPadding()
local _, itemSpacingH = self:GetItemSpacing()
local columnCount = self:GetColumnCount()
local width = self:GetWidth() - left - right - (columnCount-1) * itemSpacingH - self:GetScrollBarFixedWidth()
self._itemWidth = width / columnCount
return self._itemWidth
end
return self._itemWidth or 20
end
function GridView:SetItemSpacing(itemSpacingV, itemSpacingH)
self.itemSpacingV, self.itemSpacingH = itemSpacingV, itemSpacingH
end
function GridView:GetItemSpacing()
return self.itemSpacingV or 0,
self.itemSpacingH or self.itemSpacingV or 0
end
function GridView:GetScrollBarFixedWidth()
return self.scrollBar:IsShown() and self.scrollBar:GetWidth() or 0
end
function GridView:SetScrollStep(scrollStep)
self.scrollBar.scrollStep = scrollStep
self.scrollBar:SetValueStep(scrollStep)
-- self.scrollBar:SetStepsPerPage(scrollStep)
end
function GridView:GetScrollStep()
return self.scrollBar.scrollStep
end