• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

TEXT frame with scrolling

Level 20
Joined
May 16, 2012
Messages
635
Hello Hive,

I have been playing around with UI Frames lately and right now I'm trying to create a description frame for my new system, the problem is that I want the looks of a TEXT frame type with the scrolling functionality of a TEXTAREA frame type. The other way around works as well, a TEXTAREA with its native scrolling functionality but with the looks of a TEXT frame (less line spacing and utilizing all the vertical and horizontal space available). For example, this is the results I'm having right now:

First I tried with just a TEXT frame type and it looks exactly how I want it, but the text that overflow the given area is not displayed and I don't want it to be dynamic (that is why I need the scrolling)

JASS:
BlzCreateFrameByType("TEXT", "", parent, "", 0)

TEXT description.png


And using the TEXTAREA I get scrolling, but as you can see the line spacing is just huge, and the worst of all, it does not use all the vertical and horizontal space available

JASS:
BlzCreateFrameByType("TEXTAREA", "", parent, "", 0)

TEXTAREA description.png


I did try finding a solution or a hint in the forums but the closest thing was a post by @Tasyen here but it is using the TEXTAREA frame type as well. There he defines a FDF with some configurations that I tried as well, but the result was the same:

Code:
Frame "TEXTAREA" "DescriptionArea" INHERITS WITHCHILDREN "BattleNetTextAreaTemplate" {
    DecorateFileNames,
    FrameFont "MasterFont", 0.020, "",
    TextAreaLineHeight 0.005,
}

JASS:
BlzCreateFrame("DescriptionArea", parent, 0, 0)

So, is there a way I can configure (in code or in the FDF file) the TEXTAREA frame to look like the TEXT frame or the other way around, add the scrolling functionality to the TEXT frame? @Tasyen you might be the guy to answer this.
 
Level 12
Joined
Jan 10, 2023
Messages
191
Code:
Frame "TEXTAREA" "DescriptionArea" INHERITS WITHCHILDREN "BattleNetTextAreaTemplate" {
    DecorateFileNames,
    FrameFont "MasterFont", 0.020, "",
    TextAreaLineHeight 0.005,
}

Tasyen had this snippet withing a spoiler, slightly above the one you used

Code:
IncludeFile "UI\FrameDef\UI\EscMenuTemplates.fdf", //Frames from that fdf can be inherited in this file
IncludeFile "UI\FrameDef\UI\QuestDialog.fdf",

Frame "TEXTAREA" "MyTextArea" {
    DecorateFileNames,
    FrameFont "InfoPanelTextFont", 0.020, "",

    TextAreaLineHeight 0.018, //Should fit used font Size, a high difference shows no text or much space between lines.

    TextAreaLineGap 0.00,     //adds that much space between 2 Lines, addtional to TextAreaLineHeight.

    TextAreaInset 0.035,      //Moves the Text and the scrollbar into the middle from all sides by this amount. This increases the min size for game crash.

    TextAreaMaxLines 20,      //Only that amount of lines are displayed, if more lines are added oldest are removed.

    TextAreaScrollBar "MyTextAreaScrollBar",
    Frame "SCROLLBAR" "MyTextAreaScrollBar" INHERITS WITHCHILDREN "EscMenuScrollBarTemplate" {
    }

    ControlBackdrop "MyTextAreaBackdrop",
    Frame "BACKDROP" "MyTextAreaBackdrop" INHERITS "QuestButtonBaseTemplate" {
    }
}

Judging from that, I'm wondering if this line is what you need

Code:
Frame "TEXTAREA" "DescriptionArea" INHERITS WITHCHILDREN "BattleNetTextAreaTemplate" {
    DecorateFileNames,
    FrameFont "MasterFont", 0.020, "",
    TextAreaLineHeight 0.005,
    TextAreaLineGap 0.00,     // <- The Line I added
}

I'm a newbie with frames, which is why I read this (figured I may learn something), but of course might also mean my words are useless!
 
Level 20
Joined
May 16, 2012
Messages
635
Tasyen had this snippet withing a spoiler, slightly above the one you used

Code:
IncludeFile "UI\FrameDef\UI\EscMenuTemplates.fdf", //Frames from that fdf can be inherited in this file
IncludeFile "UI\FrameDef\UI\QuestDialog.fdf",

Frame "TEXTAREA" "MyTextArea" {
    DecorateFileNames,
    FrameFont "InfoPanelTextFont", 0.020, "",

    TextAreaLineHeight 0.018, //Should fit used font Size, a high difference shows no text or much space between lines.

    TextAreaLineGap 0.00,     //adds that much space between 2 Lines, addtional to TextAreaLineHeight.

    TextAreaInset 0.035,      //Moves the Text and the scrollbar into the middle from all sides by this amount. This increases the min size for game crash.

    TextAreaMaxLines 20,      //Only that amount of lines are displayed, if more lines are added oldest are removed.

    TextAreaScrollBar "MyTextAreaScrollBar",
    Frame "SCROLLBAR" "MyTextAreaScrollBar" INHERITS WITHCHILDREN "EscMenuScrollBarTemplate" {
    }

    ControlBackdrop "MyTextAreaBackdrop",
    Frame "BACKDROP" "MyTextAreaBackdrop" INHERITS "QuestButtonBaseTemplate" {
    }
}

Judging from that, I'm wondering if this line is what you need

Code:
Frame "TEXTAREA" "DescriptionArea" INHERITS WITHCHILDREN "BattleNetTextAreaTemplate" {
    DecorateFileNames,
    FrameFont "MasterFont", 0.020, "",
    TextAreaLineHeight 0.005,
    TextAreaLineGap 0.00,     // <- The Line I added
}

I'm a newbie with frames, which is why I read this (figured I may learn something), but of course might also mean my words are useless!
I saw that spoiler as well, and no, adding the LineGap line didn't change anything
 
Level 12
Joined
Jan 10, 2023
Messages
191
Well I'm about to leave it to others who know more, but one other thing I noticed is this:

Code:
    FrameFont "MasterFont", 0.020, "",
    TextAreaLineHeight 0.005, // <- Should fit used font Size, a high difference shows no text or much space between lines.

a high difference shows no text or much space between lines.
Tasyen had his line height at 0.018, only 0.002 less than the font, yours is 0.015 less, maybe that's it ?

That's all I got, hopefully someone more knowledgeable comes along. Goodluck!
 
Level 20
Joined
May 16, 2012
Messages
635
Well I'm about to leave it to others who know more, but one other thing I noticed is this:

Code:
    FrameFont "MasterFont", 0.020, "",
    TextAreaLineHeight 0.005, // <- Should fit used font Size, a high difference shows no text or much space between lines.

a high difference shows no text or much space between lines.
Tasyen had his line height at 0.018, only 0.002 less than the font, yours is 0.015 less, maybe that's it ?

That's all I got, hopefully someone more knowledgeable comes along. Goodluck!
Nope, same result
 
you should use other values for the textarea in fdf
TextAreaInset 0.006,
DecorateFileNames,
FrameFont "MasterFont", 0.010, "",
TextAreaLineHeight 0.0105,
TextAreaLineGap 0.0,


when you don't set a new value it will take the one from the inherited.
TextAreaInset 0.01, is kinda big
Code:
// --- TEXTAREA -----------------------------------------------------------------
Frame "TEXTAREA" "BattleNetTextAreaTemplate" {
    //DecorateFileNames,
    //FrameFont "MasterFont", 0.011, "",
    TextAreaLineHeight 0.015,
    TextAreaLineGap 0.0,
    TextAreaInset 0.01,

One could make a text scrollable by map script. Use FRAMEEVENT_MOUSE_WHEEL to push the current starting point/page and change the text.
 
Level 20
Joined
May 16, 2012
Messages
635
you should use other values for the textarea in fdf
TextAreaInset 0.006,
DecorateFileNames,
FrameFont "MasterFont", 0.010, "",
TextAreaLineHeight 0.0105,
TextAreaLineGap 0.0,


when you don't set a new value it will take the one from the inherited.
TextAreaInset 0.01, is kinda big
Code:
// --- TEXTAREA -----------------------------------------------------------------
Frame "TEXTAREA" "BattleNetTextAreaTemplate" {
    //DecorateFileNames,
    //FrameFont "MasterFont", 0.011, "",
    TextAreaLineHeight 0.015,
    TextAreaLineGap 0.0,
    TextAreaInset 0.01,

One could make a text scrollable by map script. Use FRAMEEVENT_MOUSE_WHEEL to push the current starting point/page and change the text.
Ok, so with @Tasyen tips I managed to get a step ahead, so I did:

Code:
Frame "TEXTAREA" "DescriptionArea" {
    TextAreaLineHeight 0.0105,
    TextAreaLineGap 0.0,
    TextAreaInset 0.001
}

and got

TEXTAREA adjusted.png


As you can see, line spacing is ok now, but it still leaving a lot of the available space unused. I lowered the inset to 0.001 but it had no effect on that.

One could make a text scrollable by map script. Use FRAMEEVENT_MOUSE_WHEEL to push the current starting point/page and change the text.
That would be the best for me, but what natives would I call to get the current first and last line and what natives would I call to increased or decrease it? Any examples of that anywhere?
 
Level 20
Joined
May 16, 2012
Messages
635
So, I discovered some weird behavior of the TextAreaInset property inside the FDF file. If it is in the last line of the frame definition it will not take effect

Code:
Frame "TEXTAREA" "DescriptionArea" {
    TextAreaLineHeight 0.0105,
    TextAreaLineGap 0.0,
    TextAreaInset 0.001
}

But if it not in the last line it works.

Code:
Frame "TEXTAREA" "DescriptionArea" {
    TextAreaLineHeight 0.0105,
    TextAreaInset 0.0,
    TextAreaLineGap 0.0
}

It doesn't make the text use the right space completely so to fix that I just increased the frame width and now I got what I wanted. the only annoying thing now is that the text is always in the last line. Is there a way to reset it back to the top?

TEXTAREA adjusted2.png
 
Level 14
Joined
Feb 7, 2020
Messages
387
If you can't get TEXTAREA to work, I put together a prototype of a scrolling feature using a TEXT frame as an option to maintain full control over the formatting. It's probably not optimized, but it works.

It's not sync-safe because there's no local player checks and it's adjusting game state within pairs, so that would have to be considered and added based on how you are storing tooltip text and updating framehandle values.

There's the gotcha that this requires a frame event, so the frame has to be visible and in focus of the cursor.

Lua:
SCROLLABLE_FRAMES_TEXT = {} -- table where scrollable frames can be stored to dynamically update all of them.

do
    -- https://stackoverflow.com/questions/46746752/parsing-lua-strings-more-specifically-newlines
    function string.index_by_line_break(input_string)
        local indexed_string_table = {}
        local ln = 1
        for line, newline in input_string:gmatch"([^\r\n]*)([\r\n]*)" do
            indexed_string_table[ln] = line
            ln = ln + #newline:gsub("\n+", "\0%0\0"):gsub(".%z.", "."):gsub("%z", "")
        end
        return indexed_string_table
    end
    function string.get_string_from_index_table(string_table, min, max)
        local new_s = ""
        for idx = min, max do
            new_s = new_s..string_table[idx].."\n"
        end
        return new_s
    end


    -- create scrollable frame:
    local mgs = MarkGameStarted
    function MarkGameStarted()
        mgs()

        -- frame 1
        local fh = BlzCreateFrameByType("TEXT", "MyTooltip", BlzGetOriginFrame(ORIGIN_FRAME_GAME_UI, 0), "", 0)
        SCROLLABLE_FRAMES_TEXT[fh] = {}
        SCROLLABLE_FRAMES_TEXT[fh].text_original = "Some\nScrollable\nButton\nText\nUsing\nAuto\nIndexing\n1\n2\n3\n4\n5\n6"
        SCROLLABLE_FRAMES_TEXT[fh].text_indexed = string.index_by_line_break(SCROLLABLE_FRAMES_TEXT[fh].text_original)
        SCROLLABLE_FRAMES_TEXT[fh].scrollable_index_window = 5
        SCROLLABLE_FRAMES_TEXT[fh].current_index_min = 1
        SCROLLABLE_FRAMES_TEXT[fh].current_index_max = SCROLLABLE_FRAMES_TEXT[fh].scrollable_index_window
        BlzFrameSetAbsPoint(fh, FRAMEPOINT_CENTER, 0.4, 0.3)
        BlzFrameSetText(fh, string.get_string_from_index_table(
                SCROLLABLE_FRAMES_TEXT[fh].text_indexed,
                SCROLLABLE_FRAMES_TEXT[fh].current_index_min,
                SCROLLABLE_FRAMES_TEXT[fh].current_index_max
            )
        )
        BlzFrameSetSize(fh, 0.2, 0.1)
        BlzFrameSetVisible(fh, true)

        -- trigger
        local t = CreateTrigger()
        for s_fh,_ in pairs(SCROLLABLE_FRAMES_TEXT) do
            BlzTriggerRegisterFrameEvent(t, s_fh, FRAMEEVENT_MOUSE_WHEEL)
        end
        TriggerAddAction(t, function()
            ClearTextMessages()
            TEMP_FH = BlzGetTriggerFrame()
            TEMP_SHIFT_INDEX = 0

            -- debug:
            print("TEMP_FH", TEMP_FH)
            print("Size of indexed text:", #SCROLLABLE_FRAMES_TEXT[TEMP_FH].text_indexed)

            -- get the mouse scroll direction:
            if BlzGetTriggerFrameValue() > 0 then
                TEMP_SHIFT_INDEX = -1
            else
                TEMP_SHIFT_INDEX = 1
            end
            -- print the index window to the frame:
            TEMP_TEXT = ""
            SCROLLABLE_FRAMES_TEXT[TEMP_FH].current_index_max = SCROLLABLE_FRAMES_TEXT[TEMP_FH].current_index_max + TEMP_SHIFT_INDEX
            SCROLLABLE_FRAMES_TEXT[TEMP_FH].current_index_min = SCROLLABLE_FRAMES_TEXT[TEMP_FH].current_index_min + TEMP_SHIFT_INDEX
            -- check if we exceeded the max index size:
            SCROLLABLE_FRAMES_TEXT[TEMP_FH].current_index_max = math.min(
                SCROLLABLE_FRAMES_TEXT[TEMP_FH].current_index_max,
                #SCROLLABLE_FRAMES_TEXT[TEMP_FH].text_indexed
            )
            -- if direction is negative, verify we aren't below the max window size:
            SCROLLABLE_FRAMES_TEXT[TEMP_FH].current_index_max = math.max(
                SCROLLABLE_FRAMES_TEXT[TEMP_FH].current_index_max,
                SCROLLABLE_FRAMES_TEXT[TEMP_FH].scrollable_index_window
            )
             -- restrict minimum window value:
             SCROLLABLE_FRAMES_TEXT[TEMP_FH].current_index_min = math.max(
                SCROLLABLE_FRAMES_TEXT[TEMP_FH].current_index_max + 1 - SCROLLABLE_FRAMES_TEXT[TEMP_FH].scrollable_index_window,
                1
            )
            -- build windowed text:
            TEMP_TEXT = string.get_string_from_index_table(
                SCROLLABLE_FRAMES_TEXT[TEMP_FH].text_indexed,
                SCROLLABLE_FRAMES_TEXT[TEMP_FH].current_index_min,
                SCROLLABLE_FRAMES_TEXT[TEMP_FH].current_index_max
            )

            -- debug:
            print("TEMP_SHIFT_INDEX", TEMP_SHIFT_INDEX)
            print("TEMP_TEXT", TEMP_TEXT)
            print("current_index_min", SCROLLABLE_FRAMES_TEXT[TEMP_FH].current_index_min)
            print("current_index_max", SCROLLABLE_FRAMES_TEXT[TEMP_FH].current_index_max)

            BlzFrameSetText(TEMP_FH, TEMP_TEXT)
        end)
    end
end
 

Attachments

  • z_interface_sandbox.w3m
    96.1 KB · Views: 10
Last edited:
Level 3
Joined
Jun 5, 2021
Messages
12
So, I discovered some weird behavior of the TextAreaInset property inside the FDF file. If it is in the last line of the frame definition it will not take effect

Code:
Frame "TEXTAREA" "DescriptionArea" {
    TextAreaLineHeight 0.0105,
    TextAreaLineGap 0.0,
    TextAreaInset 0.001
}

But if it not in the last line it works.

Code:
Frame "TEXTAREA" "DescriptionArea" {
    TextAreaLineHeight 0.0105,
    TextAreaInset 0.0,
    TextAreaLineGap 0.0
}

It doesn't make the text use the right space completely so to fix that I just increased the frame width and now I got what I wanted. the only annoying thing now is that the text is always in the last line. Is there a way to reset it back to the top?

View attachment 427226
No, there is something wrong with your code so it doesn't work properly, there is a missing symbol ',' at the end of the code. :wink:
 
Top