Bug - does not line wrap very long components inside a nested block
avighnac opened this issue · 2 comments
I have tested this on latest bleeding edge version (pulled the source and compiled myself), and it, unfortunately, fails to display them correctly.
JSON file
test.json:
{
"add_fraction": {
"410316161936543210318350169581764580736439706176897187461658745638794056381701649193496832507908441/110671625084041270369510745874519827349056231468761863406526354819216040200965715245470578016585408 780107824732963918497386127905416971547624143459884572049407936047104618365218009083504802769369177/682940054189039580356617302601487398249912223437990021245684561942032321432853067545223611875328379": 2.485323
}
}
Command
json-tui test.json
Without the nested { ... }
as a value to the add_fraction key, it works as expected:
However, adding one makes the line wrapping functionality break,
I believe the problem is in two-places(within main_ui.cpp):
Referring to point 1: The key-values are represented as paragraphs. The paragraph function splits text at every word (i.e., at every space/" "). The JSON you supplied includes a single space, which accounts for why it wraps in the first image.
Referring to point 2: The keys are represented by the text() element, meaning they will extend off screen without wrapping, see your second image. This could be remedied by allowing the user to scroll horizontally (frame + focusPosition decorators).
My duct-tape solution to view the entire key was to simply split the string every 40 characters & add them to a flexbox. This still leaves a single problem, when the key is too long, it pushes the contents off screen, because it is using a horizontal box in the renderer of FromKeyValue()
Before expanding
My very terrible implementation intended as a proof of concept
60 Element wrapText(std::string input_string) {
61 Elements split_string = {};
62 if (input_string.length() > 40) {
63 size_t lastPos = 0;
64 size_t nextPos = 40;
65 while (nextPos != lastPos) {
66 split_string.push_back(text(input_string.substr(lastPos, nextPos))); ‣x: text(input_string.substr(lastPos, nextPos)) ‣text: input_string.substr(lastPos, nextPos
67 lastPos = nextPos;
68 nextPos = (input_string.length() - lastPos > 40) ? lastPos + 40 : input_string.length();
69 }
70 }
71 return flexbox(split_string);
72 }
The Text class/decorator for reference
19 class Text : public Node {
20 public:
21 explicit Text(std::string text) : text_(std::move(text)) {} ‣t: text
22
23 void ComputeRequirement() override {
24 requirement_.min_x = string_width(text_);
25 requirement_.min_y = 1;
26 }
27
28 void Render(Screen& screen) override {
29 int x = box_.x_min;
30 const int y = box_.y_min;
31 if (y > box_.y_max) {
32 return;
33 }
34 for (const auto& cell : Utf8ToGlyphs(text_)) { ‣input: text_ ‣: basic_string<char> const &
35 if (x > box_.x_max) {
36 return;
37 }
38 screen.PixelAt(x, y).character = cell;
39 ++x;
40 }
41 }
42
43 private:
44 std::string text_;
45 };
The Paragraph & Split functions for reference:
11 Elements Split(const std::string& the_text) {
12 Elements output;
13 std::stringstream ss(the_text); ‣str: the_text
14 std::string word;
15 while (std::getline(ss, word, ' ')) { ‣in: ss ‣str: word ‣delim: ' '
16 output.push_back(text(word)); ‣x: text(word) ‣text: word
17 }
18 return output;
19 }
20 } // namespace
22 /// @brief Return an element drawing the paragraph on multiple lines.
25 Element paragraph(const std::string& the_text) {
26 return paragraphAlignLeft(the_text); ‣text: the_text
27 }
33 Element paragraphAlignLeft(const std::string& the_text) {
34 static const auto config = FlexboxConfig().SetGap(1, 0); ‣gap_x: 1 ‣gap_y: 0 ‣: const FlexboxConfig
35 return flexbox(Split(the_text), config);
36 }