|
611 | 611 | -- Inline "X/255" indicator anchored to the top-right of the macro edit box, |
612 | 612 | -- replacing the old side-panel that listed compiled output. Created on first |
613 | 613 | -- call; subsequent calls just retext + recolour. |
| 614 | +-- Size the macro-commands box to its content: one row per line of macro |
| 615 | +-- text, never fewer than MACRO_BOX_MIN_LINES (short blocks keep a usable |
| 616 | +-- box), never more than MACRO_BOX_MAX_LINES (a huge block scrolls instead |
| 617 | +-- of swallowing the window). Re-fitted as the user types; only re-lays out |
| 618 | +-- when the row count actually changes so fast typing stays cheap. |
| 619 | +local MACRO_BOX_MIN_LINES = 3 |
| 620 | +local MACRO_BOX_MAX_LINES = 24 |
| 621 | +-- Rows the widget is BUILT at, before the first fit runs. This has to stay in |
| 622 | +-- step with macrolayout's SetHeight(108) below -- NativeUI's SetNumLines(n) is |
| 623 | +-- n * 16 + STYLE.frameContentTop (28), so 5 rows is exactly 108. The fit pushes |
| 624 | +-- the DELTA from this baseline up through the fixed-height ancestors, so a |
| 625 | +-- baseline that disagrees with the container leaves that much dead space under |
| 626 | +-- the box. It is NOT the minimum -- MACRO_BOX_MIN_LINES is, and is free to move |
| 627 | +-- on its own. |
| 628 | +local MACRO_BOX_BASE_LINES = 5 |
| 629 | +-- Slack the fitted frame carries over the measured text, and the floor NativeUI |
| 630 | +-- clamps the inner editbox to (updateEditBoxSize). At a small chat font the |
| 631 | +-- min-row fit lands under that floor and the bottom row would render outside |
| 632 | +-- the visible scroll area, so the frame is never asked for less. |
| 633 | +local MACRO_BOX_CHROME_SLACK = 6 |
| 634 | +local MACRO_BOX_MIN_INNER = 40 |
| 635 | +-- Rows -> pixels in the box's OWN font: a row is the measured line height, and |
| 636 | +-- every row after the first also carries the editbox's line spacing. |
| 637 | +local function MacroBoxRowsHeight(rows, oneRow, spacing) |
| 638 | + return rows * oneRow + math.max(rows - 1, 0) * spacing |
| 639 | +end |
| 640 | +local function FitMacroEditBoxToContent(macroEditBox, text) |
| 641 | + if not (macroEditBox and macroEditBox.SetHeight) then return end |
| 642 | + local eb = macroEditBox.editBox or macroEditBox.editbox |
| 643 | + if not eb then return end |
| 644 | + local plain = text or "" |
| 645 | + if GSE.DecodeMacroEditorText then plain = GSE.DecodeMacroEditorText(plain) or plain end |
| 646 | + plain = tostring(plain) |
| 647 | + -- Stored macro text commonly ends with a newline; that trailing newline is |
| 648 | + -- not a row the author sees as content, so it is not measured -- EXCEPT |
| 649 | + -- while the author is typing on that last empty row (box focused, caret at |
| 650 | + -- the end), so pressing Enter at the bottom still opens the new row. |
| 651 | + local body = plain:gsub("\n+$", "") |
| 652 | + local typingOnTrailingRow = #body < #plain and eb.HasFocus and eb:HasFocus() |
| 653 | + and eb.GetCursorPosition and eb.GetText and eb:GetCursorPosition() >= #(eb:GetText() or "") |
| 654 | + |
| 655 | + -- MEASURE the rendered text height with a hidden FontString in the box's |
| 656 | + -- own font (wraps included) instead of estimating rows x font size -- |
| 657 | + -- estimates drifted by about a row and showed a spare empty line. |
| 658 | + local meter = macroEditBox.gseHeightMeter |
| 659 | + if not meter then |
| 660 | + meter = macroEditBox.frame:CreateFontString(nil, "ARTWORK") |
| 661 | + meter:Hide() |
| 662 | + macroEditBox.gseHeightMeter = meter |
| 663 | + end |
| 664 | + local fontPath, fontSize, fontFlags = eb:GetFont() |
| 665 | + if fontPath then meter:SetFont(fontPath, fontSize or 14, fontFlags or "") end |
| 666 | + local spacing = (eb.GetSpacing and eb:GetSpacing()) or 0 |
| 667 | + if meter.SetSpacing then meter:SetSpacing(spacing) end |
| 668 | + meter:SetWordWrap(true) |
| 669 | + local width = eb:GetWidth() or 0 |
| 670 | + meter:SetWidth(width > 50 and width or 600) |
| 671 | + meter:SetText("X") |
| 672 | + local oneRow = meter:GetStringHeight() or (fontSize or 14) |
| 673 | + if oneRow <= 0 then oneRow = fontSize or 14 end |
| 674 | + meter:SetText(body ~= "" and body or "X") |
| 675 | + local textHeight = meter:GetStringHeight() or oneRow |
| 676 | + if typingOnTrailingRow then textHeight = textHeight + oneRow + spacing end |
| 677 | + textHeight = |
| 678 | + math.max( |
| 679 | + MacroBoxRowsHeight(MACRO_BOX_MIN_LINES, oneRow, spacing), |
| 680 | + math.min(MacroBoxRowsHeight(MACRO_BOX_MAX_LINES, oneRow, spacing), textHeight) |
| 681 | + ) |
| 682 | + textHeight = math.max(textHeight, MACRO_BOX_MIN_INNER - MACRO_BOX_CHROME_SLACK) |
| 683 | + |
| 684 | + local chrome = |
| 685 | + (macroEditBox.labelHeight or 12) + (macroEditBox.verticalOffset or 2) * 3 + MACRO_BOX_CHROME_SLACK |
| 686 | + local newHeight = math.ceil(textHeight + chrome) |
| 687 | + if macroEditBox.gseFitHeight == newHeight then return end |
| 688 | + macroEditBox.gseFitHeight = newHeight |
| 689 | + local delta = newHeight - (macroEditBox.height or newHeight) |
| 690 | + macroEditBox:SetHeight(newHeight) |
| 691 | + -- The box sits under several EXPLICIT-height containers (macrolayout, |
| 692 | + -- macroFields, macroBody -- sized at draw time); auto-height ancestors |
| 693 | + -- above them only follow if those grow too. Push the delta up through |
| 694 | + -- every fixed-height ancestor, relaying out as we go. |
| 695 | + local parent = macroEditBox.parent |
| 696 | + while parent do |
| 697 | + if delta ~= 0 and parent.explicitHeight and not parent.autoAdjustHeight |
| 698 | + and parent.height and parent.SetHeight then |
| 699 | + parent:SetHeight(parent.height + delta) |
| 700 | + elseif parent.DoLayout then |
| 701 | + parent:DoLayout() |
| 702 | + end |
| 703 | + parent = parent.parent |
| 704 | + end |
| 705 | +end |
| 706 | + |
614 | 707 | local function SetMacroCountText(macroEditBox, lenMacro) |
615 | 708 | if not (macroEditBox and macroEditBox.frame) then return end |
616 | 709 |
|
@@ -5180,6 +5273,8 @@ function GSE.CreateEditor() |
5180 | 5273 | local macrolayout = UI:Create("SimpleGroup") |
5181 | 5274 | macrolayout:SetLayout("Flow") |
5182 | 5275 | macrolayout:SetFullWidth(true) |
| 5276 | + -- 108 == a MACRO_BOX_BASE_LINES-row macro box (SetNumLines: rows * 16 + |
| 5277 | + -- frameContentTop); the auto-fit measures its delta from that pairing. |
5183 | 5278 | macrolayout:SetHeight(108) |
5184 | 5279 | if macrolayout.SetFlowOffset then macrolayout:SetFlowOffset(0, 4) end |
5185 | 5280 | if macrolayout.SetFlowPadding then macrolayout:SetFlowPadding(4, 0, 4, 0) end |
@@ -5243,6 +5338,10 @@ function GSE.CreateEditor() |
5243 | 5338 | macroFields:AddChild(macrolayout) |
5244 | 5339 | macroBody:AddChild(macroRail) |
5245 | 5340 | macroBody:AddChild(macroFields) |
| 5341 | + -- Fit the macro box to its content now that it sits under its containers: |
| 5342 | + -- the fit pushes the height delta up through macrolayout/macroFields/ |
| 5343 | + -- macroBody (all explicit-height, sized above for the 108px baseline). |
| 5344 | + FitMacroEditBoxToContent(macroeditbox, macroeditbox:GetText()) |
5246 | 5345 | spellcontainer:AddChild(macroBody) |
5247 | 5346 | -- Report the COMPILED macro body length (after spell-name translation) |
5248 | 5347 | -- so the "X/255" indicator matches the over-limit trigger and what WoW |
@@ -7296,7 +7395,7 @@ function GSE.CreateEditor() |
7296 | 7395 | DisableMultilineEditorColoring(macroEditBox) |
7297 | 7396 | macroEditBox:SetLabel(L["Macro Name or Macro Commands"]) |
7298 | 7397 | macroEditBox:DisableButton(true) |
7299 | | - macroEditBox:SetNumLines(5) |
| 7398 | + macroEditBox:SetNumLines(MACRO_BOX_BASE_LINES) |
7300 | 7399 | macroEditBox:SetRelativeWidth(0.5) |
7301 | 7400 | macroEditBox:SetText(spelltext) |
7302 | 7401 | ForwardMacroEditorMouseWheel(macroEditBox, frame) |
@@ -7376,6 +7475,7 @@ function GSE.CreateEditor() |
7376 | 7475 | if compiledMacro.parent and compiledMacro.parent.DoLayout then compiledMacro.parent:DoLayout() end |
7377 | 7476 | end |
7378 | 7477 | SetMacroCountText(macroEditBox, GSE.GetMacroEditorTextLength(value or "")) |
| 7478 | + FitMacroEditBoxToContent(macroEditBox, value) |
7379 | 7479 | UpdateMacroLimitState(macroEditBox, sequence.Versions[version].Actions[keyPath].macro, editframe, version) |
7380 | 7480 | end |
7381 | 7481 | ) |
|
0 commit comments