import "Turbine.UI";
import "Turbine.UI.Lotro";
-- Adds AutoSize() function to Turbine.UI.Label
-- It works for single or multiline strings.
-- Not yet tested with inline markup.
-- Adds AutoSize() function to Turbine.UI.Window and Turbine.UI.Lotro.Window.
-- Adds AutoSize() function to Turbine.UI.Control, to set the size according to the background image size.
-- Get font heights from enumeration strings
local FontHeight = {};
for key, value in pairs(Turbine.UI.Lotro.Font) do
FontHeight[value] = tonumber(string.match(key, "[0-9]+$", -3));
end
-- Override SetMultiLine() because the built-in IsMultiline() function doesn't work and we need to fix it
Turbine.UI.Label._SetMultiline = Turbine.UI.Label.SetMultiline;
function Turbine.UI.Label:SetMultiline(enable)
Turbine.UI.Label._SetMultiline(self, enable);
self.multiline = enable;
if (self.autoSizingEnabled) then
self:AutoSize();
end
end
function Turbine.UI.Label:IsMultiline()
return ((self.multiline == true) or (self.multiline == nil));
end
function Turbine.UI.Label:AutoSize()
-- Save this to restore afterwards
local text = self:GetText();
local userScrollBar = self:GetHorizontalScrollBar();
self:SetHorizontalScrollBar(nil);
self:_SetMultiline(false);
-- Add extra width for the outline, if any
local outline = 0;
if (self:GetFontStyle() == Turbine.UI.FontStyle.Outline) then
outline = 1; -- to do: is this bigger for larger fonts?
end
-- We can set the height based on the selected font and the number of '\n' characters present
local lineHeight = FontHeight[self:GetFont()];
self:SetHeight(lineHeight + outline);
-- Make a temporary scrollbar that whose visibility will indicate text width
local tempScrollBar = Turbine.UI.Lotro.ScrollBar();
tempScrollBar:SetParent(self);
self:SetHorizontalScrollBar(tempScrollBar);
-- Magic function call that is necessary to make the ScrollBar:IsVisible() function work
self:SetText(text);
local function autoSizeLine()
self:SetWidth(64);
-- Rapidly find lower and upper bounds for the possible widths.
local lower_bound, upper_bound = 0, 64;
local visible = tempScrollBar:IsVisible();
while (visible) do
--Puts("\"" .. tostring(self:GetText()) .. "\" is wider than " .. upper_bound);
lower_bound = upper_bound;
upper_bound = 2 * upper_bound;
self:SetWidth(upper_bound);
visible = tempScrollBar:IsVisible();
end
-- Binary search for the precise width. Fractions are OK; they are handled by the API.
local width, distance = self:GetWidth();
repeat
if (tempScrollBar:IsVisible()) then
--Puts("\"" .. tostring(self:GetText()) .. "\" is wider than " .. width);
lower_bound = width;
else
--Puts("\"" .. tostring(self:GetText()) .. "\" is narrower than " .. width);
upper_bound = width;
end
distance = upper_bound - lower_bound;
width = lower_bound + math.floor(0.5 + distance / 2);
self:SetWidth(width);
until (distance <= 1);
return width + outline;
end
if (not self:IsMultiline()) then
self:SetWidth(autoSizeLine());
else
-- If multiline, run once for each line and use the widest line to set the overall width.
local numLines, maxWidth, _ = 0, 0;
for line in string.gmatch(self:GetText(), "[^\n]+") do
numLines = numLines + 1;
self:SetText(line);
maxWidth = math.max(maxWidth, autoSizeLine());
end
maxWidth = maxWidth + lineHeight; -- fudge that seems necessary to account for phantom width of "\n" character
self:_SetMultiline(true);
self:SetSize(maxWidth, numLines * lineHeight + outline);
self:SetText(text);
end
tempScrollBar:SetParent(nil);
-- Restore user's scrollbar (if any)
self:SetHorizontalScrollBar(userScrollBar);
return self;
end
-- Figures x-margin from the leftmost child control's position.
-- Figures y-margin from the topmost child control's position.
-- Sets the window width to the right of the rightmost child control, plus the x-margin.
-- Sets the window height to the bottom of the bottom-most child control, plus the y-margin.
function Turbine.UI.Window.AutoSize(self)
local xmin, ymin, xmax, ymax = 500, 500, 0, 0;
local children = self:GetControls();
for c = 1, children:GetCount() do
local child = children:Get(c);
--child:SetBackColor(Turbine.UI.Color.Red);
local left, top = child:GetPosition();
local width, height = child:GetSize();
xmin = math.min(xmin, left);
ymin = math.min(ymin, top);
xmax = math.max(xmax, left + width);
ymax = math.max(ymax, top + height);
end
self:SetSize(xmax + xmin, ymax + ymin);
end
-- Lotro window has the title at the top, so for symmetry, we need to reduce the y-margin on the bottom.
function Turbine.UI.Lotro.Window.AutoSize(self)
Turbine.UI.Window.AutoSize(self);
self:SetHeight(self:GetHeight() - 13);
end
-- Function for determining text size by creating a temporary label
function _G.GetTextWidth(font, text)
local label = Turbine.UI.Label();
label:SetMultiline(false);
label:SetFont(font);
label:SetText(text);
label:AutoSize();
return label:GetWidth();
end
function Turbine.UI.Control.AutoSize(self)
self:SetStretchMode(2); -- resize to image's native size
self:SetStretchMode(0);
end